目录

组件之间的通讯

# 组件之间的通讯

Vue组件之间的通讯有多种方法:①父组件给子组件传值。②子组件给父组件传值。③兄弟组件之间的传值。组件之间的通讯在实际开发中可增加代码的重用性和扩展性。

# 父组件给子组件传值

组件是当作自定义元素来使用的,HTML元素有属性,同样,组件也可以有属性,利用属性给子组件内部传值,子组件使用props来接收。代码如下:

//子组件
    let ChildrenComponent={
        //使用props接收属性
        props:["post-title","sub-title"],
        template:`
            <div>{{postTitle}}-{{subTitle}}</div>
        `
    };
//父组件
    let ParentComponent={
        data(){
            return {
                title:"我是父组件的title",
                subTitle:"我是父组件的subTitle"
            }
        },
          template: `
            <div>
                <ChildrenComponent :post-title="title" :sub-title="subTitle"></ChildrenComponent>
            </div>
          `,
        components:{
            ChildrenComponent
        }
    };
new Vue({
        el:"#app",
        components:{
            ParentComponent
        },
        template:`
            <div>
                <ParentComponent></ParentComponent>
            </div>
        `
    })
注意:接收的属性名是kebab-case(短横线分隔命名)来使用,在Mustache标签里面变量名要用camelCase(驼峰命名)来使用,因为Mustache标签不支持kebab-case。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

Vue还支持属性类型的验证,比如子组件接收的属性值应该是一个对象类型,结果父组件传的是一个字符串类型的值,这显然不符合要求,这时需要属性验证。代码示例如下:

//使用props接收属性并验证类型
        props:{
            "post-title":{
                type:String
            },
            "sub-title":{
                type:String
            }
        },

1
2
3
4
5
6
7
8
9
10

验证的type值可以是下列原生构造函数中的一个:

  • lString
  • lNumber
  • lBoolean
  • lArray
  • lObject
  • lDate
  • lFunction
  • lSymbol

在实际开发中推荐使用验证属性的方式接收prop。

验证属性的方式还支持,父组件传过来的属性是否为必有属性,代码如下:

 props:{
      "post-title":{
        type:String,
        required:true //父组件必须传入此属性
      }
    },
1
2
3
4
5
6

验证属性的方式还支持默认值,在组件没有传入属性的时候,可以给一个默认值,代码如下:

//使用props接收属性并验证类型
        props:{
            "post-title":{
                type:String,
                default:"我是post-title默认值"
            }
        },

1
2
3
4
5
6
7
8

如果是Array或Object类型默认值需要用工厂函数返回,代码如下:

props:{
            "list":{
                type:Array,
                default:()=>[] //工厂函数返回默认值
            }
        },

1
2
3
4
5
6
7

组件也可以接收任意的属性,比如给组件添加class或style属性等,而这些外部设置的属性会被添加到这个组件的跟元素上面。代码如下:

 //子组件
    let InputComponent={
        template:`
                <input type="text" class=" input"  />
        `
    };
   //父组件
    let ParentComponent={
          template: `
            <div>
                <InputComponent class="my-input"></InputComponent>
            </div>
          `,
        components:{
            InputComponent
        }
    };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

而对于其他属性而言,则会覆盖,代码如下:

//父组件
 <InputComponent class="my-input" type="checkbox" checked></InputComponent><InputComponent>组件上面添加属性type和checked,InputComponent组件内部根元素input存在属性type则覆盖,最终type的值为checkbox,checked属性不存在,则添加checked属性。

1
2
3
4
5

如果不希望根组件继承外部设置的属性,可以在子组件的选项中设置属性inheritAttrs的值为false,代码如下:

 //子组件
    let InputComponent={
        template:`
                <input type="text" class="input" />
        `,
        inheritAttrs:false//根元素不继承外部设置的属性
    };

1
2
3
4
5
6
7
8

由于prop传递数据属于单向数据流,父组件的属性变化会向下传递给子组件,但是反过来却不行,这可以防止子组件意外改变父组件的状态,从而导致应用程序的数据流难以理解。每次父组件更新数据时,子组件的prop都会刷新为最新的值。这意味着我们不应该在组件内部直接更改prop,如果更改Vue会在浏览器的控制台中给出警告。

可以使用本地的data方法或是引用类型来解决。

# 子组件给父组件传值

在Vue中是通过自定义事件来实现的,子组件使用$emit()方法触发事件,父组件使用v-on指令监听子组件的自定义事件来完成通讯。

$emit()方法的语法形式如下:

vue.$emit(eventName,[...args])

eventName是自定义事件名称,args是附加参数

# 兄弟组件之间传值

在实际开发中也会出现兄弟组件(非父子组件)之间传值的需求,实现的方式很简单,声明一个bus变量其值为new Vue(),然后在A组件bus.$emit()方法传值,B组件用bus.$on方法接收A组件传过来的值,来完成兄弟组件之间的传值。

# 父组件与子组件实现双向绑定

在开发UI库时都是对HTML表单控件进行封装的,比如自定义了一个input组件,在自定义的input组件上面添加v-model指令,默认v-model指令是不生效的,这时我们要手动让它支持v-model指令,常用的解决方案有两种:

第一种使用computed解决,第二种使用model解决。

# 父组件调用子组件的方法

在实际开发中经常会遇到父组件调用子组件的方法,其实很简单,通过ref就可以直接调用子组件里面的方法

上次更新: 2022/06/01 11:01:52
最近更新
01
关于我
07-14
02
科学上网
11-15
03
OSS+CDN
09-23
更多文章>
极昼青春
买辣椒也用券