vue组件

141 阅读2分钟

vue组件

组件的注册

  • 组件名格式:用大驼峰<MyComponent>或者烤串式<my-component>

全局注册

  • 可以在此应用的任意组件的模板中使用
  • 可以在彼此内部使用
let app=Vue.careateApp({})
app.component(
// 注册的名字 
'MyComponent', 
// 组件的实现 
{ /* ... */ }
)
app.mount("#app")

局部注册

  • 全局组件的问题
    • 打包时,就算没有实际使用,也会在打包后的 JS 文件中
    • 依赖关系变得不那么明确,影响应用长期的可维护性
  • 局部组件之间的依赖关系更加明确,并且对 tree-shaking 更加友好
let app=Vue.careateApp({
components:{
    ComponentA
}
})

组件通信

父子通信props

  • Prop在取名时可以用小驼峰camelCase形式,然后在html中用烤串kebab-case形式
  • 在传值时,只有字符串可以静态传递,其他类型最好动态传递,因为js会默认把值识别为字符串
    • Number <BlogPost :likes="42" />
    • Boolean 直接写,默认为true,传在即为真,不写就是false <BlogPost is-published />
app.component('MyComponent', {
    //可以是数组类型props: ['foo']也可以是对象类型
    props:{
        //可以定义类型
        propA: Number,
        propB: [String, Number],
        propC: {
            type: String,
            //required 是否必传 默认可选
            required: true//default默认值 定义默认值 没有传入时的值
            default: "100",
            },
         propD:{
             //自定义效验函数 只能是这几个值中的一个
             validator(value) { 
                    return ['success', 'warning', 'danger'].includes(value) }
             }
    }
})

子父通信$emit

//触发子组件的事件函数 someEvent为自定义事件
1.直接使用
<button @click="$emit('someEvent')">click me</button>
2.`this.$emit()` 的形式
export default { 
    methods: { 
        submit() { 
            //如果孩子有东西想要传给父亲,可以在后面v入孩子的内容 也可以是对象写
            this.$emit('someEvent',v) 
            } } }
            
//父组件在调用时,绑定对应的自定义事件
<my-child @some-event="父级的事件函数"></my-child>
//孩子v的内容在父亲的事件函数中可以直接拿到
methods: { 
    父级的事件函数(n){
        console.log(n)
    } }

组件通信$refs

//html中定义ref
<div id='app'>
        <button @click="btn">按钮</button>
        <h1 ref="skyH1">这是h1</h1>
        <input type="text" ref="skyInput">
</div>

//vue中操作$refs
methods: {
    btn() {
        console.log(this.$refs);
        this.$refs.skyH1.style.color = "red"
        this.$refs.skyInput.focus()
    }
}

依赖注入(provide/inject)

  • 解决深层组件嵌套后,外层向内层传递数据的需求
  • 传入固定值
//容器组件
app.component({
   provide:{
      键名:键值
   }
})

//后代组件
app.component({
   inject:['键名']
})
  • 传入响应式数据
//容器组件
app.component({
   data(){
      return {
         响应式键名:xxx
      }
   }
   provide(){
      return {
         键名:Vue.computed(()=>{
            return this.响应式键名
         })}}})
         
 //后代组件
 app.component({
   inject:['键名']
})

拓展方法

  • 透传 Attribute $attrs
    • class 外面传到里面
    • @click 内部能够直接触发绑在组件上的点击事件 <my-comp @click=""/>
    • 组件内部,可以使用$attrs获取属性
    //props 之外的属性,才能被$attrs 拿到
     template: `<div @click="handleAdd">
                    <h2 v-bind="$attrs">{{$attrs.name}}</h2>
                </div>`
    
  • $root
    • 直接拿到根的内容
  • $parent
    • 直接拿到父级组件的内容

vuex 集中式状态管理工具

组件v-model

  • 组件需要做的两件事
      1. 将内部原生 <input> 元素的 value attribute 绑定到 modelValue prop
      1. 当原生的 input 事件触发时,触发一个携带了新值的 update:modelValue 自定义事件
//vue组件中的写法
app.component('MyComponent',{
    template:`
    <input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" />
    `
})
app.mount("#app")

//在html中调用组件时
<MyComponent v-model="msg"></MyComponent>

插槽slot

//vue中写入插槽
app.component('MyComponent',{
    template:`
    <div>
    <!-- 默认内容 -->
      <slot></slot>
     <!-- 具名插槽 -->
     <slot name="header"></slot>
     <slot name="footer" :xx="xxx"></slot>
   </div>
    `
})

//html中实际使用
<MyComponent>
    <h1>直接写用的默认插槽</h1>
    <template v-slot:header>
        <!-- header 插槽的内容放这里 --> 
    </template>
    <template #footer="{xx}">
        <!-- footer 插槽的内容放这里 #是v-slot的简写 xx是插槽内部传的内容数据包--> 
    </template>
</MyComponent>