组件实例的作用域是孤立的,这意味着不能并且不应该在子组件的模板内直接引用父组件的数据。但是父子组件之间需要通信:父组件要给子组件传递数据,子组件需要将它内部发生的事情告知给父组件。在 Vue.js 中,父子组件的关系可以总结为 props down, events up :父组件通过 props 向下传递数据给子组件,子组件通过 events 给父组件发送消息。
{{msg}}
Vue.component('com',{
template:'#com',
props:['msg'] //变量名要用引号引起
});
就像函数调用过程一样,在调用组件
结果如图,组件显示出来自父组件的不同信息:
注意:1、html不区分大小写,因此不支持使用驼峰命名法传递属性参数,例如将msg换为myMsg将无法渲染,需要将html属性中的myMsg换为短横线分割法:my-msg,而js中可以不必修改。
2、prop是单向绑定,父组件值的更新会导致子组件值改变,反之则不会,因此要避免在子组件中修改、处理props中的值。
{{myMsg}}
Vue.component('com',{
template:'#com',
props:['myMsg']
});
3、可以为组件 prop 指定验证规则。如果传入数据不符合要求,Vue 会发出警告。此时需要用对象的形式来定义 prop。
Vue.component('example', {
props: {
// 基础类型检测 (`null` 指允许任何类型)
propA: Number,
// 多种类型数组
propB: [String, Number],
// 必传且是字符串
propC: {
type: String,
required: true
},
// 数值且有默认值
propD: {
type: Number,
default: 100
},
// 数组/对象的默认值应当由一个工厂函数返回
propE: {
type: Object,
default: function () {
return { message: 'hello' };
}
},
// 自定义验证函数
propF: {
validator: function (value) {
return value > 10
}
}
}
})
在多个组件嵌套时,中间的组件不仅需要接收上层传递给自己的参数,还要接收上层传递给自己子组件的参数。类似于子类继承父类时,构造函数不仅要初始化本类的属性,还要初始化父类的属性。
注意:1、父组件向子组件传递参数为变量时需要使用绑定。
2、 props[]中的变量名、父组件向下传递时标签中的属性名、子组件使用变量时的名字是一致的,例如使用c1_msg的三个地方。
例如通过父组件parent来接收上层app组件的参数,并传给两个子组件child1与child2:
{{child_msg}}
{{child_msg}}
{{p_msg}}
在vue中注册父组件parent,设置其参数props,并在parent中注册两个子组件,设置props:
let vue=new Vue({
el:'#app',
data:{
},
components:{
'parent':{
template:'#parentDiv',
props:['p_msg','c1_msg','c2_msg'],
components:{
'c1':{
template:'#child1',
props:['child_msg']
},
'c2':{
template:'#child2',
props:['child_msg']
}
}
}
}
});
结果父组件不仅显示了自己的信息,还将信息传递给了两个子组件显示:
由于props是单向绑定,无法使用其向父组件通信。vue中使用自定义事件实现子组件向父组件的数据传递。
父组件可以使用v-on(缩写为@)来监听子组件触发的事件,当子组件中发射出标志信息后,父组件会调用相应的方法。
例如分别设置三个按钮组件对自己被点击的次数进行计数,然后父组件对三个子组件被点击的总次数进行计数,当子组件按钮被点击时调用countClick()函数将自己计数count++,同时通过this.$emit()函数父组件发送标志信息emittion。在父组件中用@监听emittion,并调用countAll()函数,使总次数allCount加一。
一共被点击{{allCount}}
let countAll=0;
let vue2=new Vue({
el:'#app2',
data:{
allCount:0
},
components:{
'btn':{
template:'#myBtn',
data (){
return {
count:0
};
},
methods:{
countClick(){
this.count++;
//发射信息标志通知上层事件被触发
this.$emit('emittion');
}
}
}
},
methods:{
countAll(){
this.allCount++;
}
}
});
结果如图:
子组件内的事件触发器不只是发送信息标志,还可以向父组件传递载荷数据,在父组件的事件处理函数中接收数据参数,例如:
//子组件发射载荷数据
this.$emit('message', { message: this.message });
//父组件监听message,并调用handleMessage函数接收playload参数
handleMessage: function (payload) { //父组件通过playload接收子组件message数据
this.messages.push(payload.message);
}
非父子组件之间通过一个Vue类Hub实现通信,一个组件在Hub一段发送标志信息及相关数据,另一个组件侦听,一旦检测到标志,就接受数据,并用回掉函数处理:
let Hub=new Vue();
Hub.$emit('emittion',data); //发送emittion及data
Hub.$on('emittion',function (data) { //检测到emittion,回调函数接收data并处理
handler();
});