父组件-->子组件通信:
1.先给父组件中绑定自定义的属性。
2.在子组件中使用props接受父组件传递的数据。
3.这时候父组件传递的数据可以在子组件中任意使用。
子组件:
<script>
Vue.component('Child',{
template:'
<div>
<p>我是一个孩子组件</p>
<input type="text" v-model='childData'/>
</div>
',
props:['childData']
})
</script>
父组件:
<script>
Vue.component('Parent',{
template:'
<div>
<p>我是一个父组件</p>
//因为上面定义了Child这个全局子组件,所以这里不需要声明该组件
<Child:childData='msg'/>
</div>
',
data(){
return{
msg:"我是父组件的数据"
}
}
})
</script>
子组件-->父组件通信:
1.在子组件中以某种方式(原生事件)来触发一个自定义事件,将需要传的值传为$emit的第二个参数,该值将作为实参传给响应的包含了自定义事件的方法。
ps:自定义的事件一定是通过$emit()方法去触发。
$emit的简单介绍:$emit("自定义的事件名",参数)
2.在父组件中注册了的子组件并在组件标签上绑定对自定义事件的监听。 即在父组件中使用了子组件的位置上加入属性 v-on自定义事件名="此组件中的方法"来获取子组件传入父组件的数据。
子组件:
<script>
Vue.component('Child',{
template:'
<div>
<p>我是一个孩子组件</p>
<input type="text" v-model='childData'/>
<button @click="sendMsgToParent">向父组件传一个值</button>
</div>
',
props:['childData'],
methods:{
sendMsgToParent:function(){
this.$emit("listenChildEvent","A message from Child");
}
})
</script>
父组件:
<script>
Vue.component('Parent',{
template:'
<div>
<p>我是一个父组件</p>
//因为上面定义了Child这个全局子组件,所以这里不需要声明该组件
<Child:childData='msg' @listenChildEvent="showMsgFromChild"/>
<!--在子组件的位置加入@自定义事件名="此组件中的方法"来获取子组件的数据-->
</div>
',
data(){
return{
msg:"我是父组件的数据"
}
},
methods:{
showMsgFromChild:function(data){
console.log(data);
}
}
})
</script>
总结:子组件--->父组件传值是通过自定义事件,而父组件-->子组件传值是通过props选项中的属性。
以上部分内容来自于: vue2.0 子组件和父组件之间的传值
嵌套组件之间的通信:
若现有嵌套组件 组件App--->组件A--->组件B--->组件C,两个相邻的组件可以通过 父组件-->子组件(props属性) 还有 子组件-->父组件(在子组件中使用$emit向父组件传值,在父组件中用v-on来接受子组件传过来的值) 相互进行通信。 若组件C需要与组件App进行跨组件的通信,那么就需要用到$attrs以及$listers向上和向下传递值(通信)。 但是若是以上面的父传子还有子传父两种方法来实现跨组件的通信,这样子就会使得业务逻辑代码臃肿并且不好去维护。
<script>
<!--App组件-->
var App={
data(){
return{
msg:"我是App组件的数据",
msgC:"你好C组件"
}
},
template:'
<div>
<p>这是父组件App组件</p>
<A :messagec='messagec' v-on:getCData:"getCData">
</div>
',
methods:{ <!--执行C组件中的触发的自定义函数-->
getCData:function(val){
console.log(val);
}
}
}
<!--A组件-->
Vue.component("A",{
template:'
<div>
<B v-bind="$attrs" v-on="$listeners"></B>
</div>
'
})
<!--B组件-->
Vue.component("B",{
template:'
<div>
<C v-bind="$attrs" v-on="$listeners"></B>
</div>
'
})
<!--C组件-->
Vue.component("C",{
template:'
<div>
<div @click="cClickHandler'> {$attrs.messagec}} </div>
</div>
',
methods:{
cClickHandler:function(){
this.$emit("getCData","我是C组组件的数据");
}
}
})
</script>
照着我自己的理解,$attrs算是props选项的一个集合,若是使用props选项来传值,那么就要在props选项中不断地写入属性来进行传值通信,这样写的代码太臃肿并且也不好去维护。
$attrs包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定(class
和 style
除外)则不需要在组件中声明任何的props这里会包含所有父作用域的绑定 (class和 style
除外),并且可以通过 v-bind="$attrs"
传入内部组件。
而$listeners包含了父作用域中的 (不含 .native
修饰器的) v-on
事件监听器。它可以通过 v-on="$listeners"
传入内部组件。
使用选项provide和inject进行通信:
1.父组件通过provide来提供变量。
<script>
var Father={
provide:{
foo:"参数信息"
}
}
</script>
2.然后在子组件中通过inject来注入变量。
<script>
var Son={
data(){
return{
msg=""
}
},
components:{Father},
inject:['foo'],
created:function(){
this.msg=this.for;
console.log(msg);
}
}
</script>
不论子组件嵌套的有多深,只要调用了inject,那么就可以注入provide中定义的数据。而不是仅仅局限于只能从当前父组件的prop属性来获取数据,只要在父组件的生命周期内子组件都可以调用。
中央事件总线:
1.新建一个Vue事件vm实例化对象,然后再通过vm.$emit触发事件,再然后vm.$on监听触发事件
<script>
<!--新建一个Vue事件vm对象-->
var vm=new Vue();
<!--简写A组件-->
methods:{
sendData:function(){
//进行传值的组件就绑定$emit事件
//dataFromA为A组件中的自定义事件,this.dataA为A组件中的数据
vm.$emit('dataFromA', this.dataA);
}
<!--简写B组件-->
methods:{
getData:funciton(){
//拿到传过来值的组件就绑定$on事件
//$on事件的第一个参数是dataFromA为A组件中的自定义事件,第二个参数为回调函数
vm.$on('dataFromA',function(data){
//回调函数中的data则为A组件传过来的值
})
</script>
组件A和组件B的关系可以是父子关系,兄弟关系等等任意关系都是可以的。
ps:
$on事件: 监听当前实例上的自定义事件。监听的事件可以由 vm.$emit
触发。回调函数会接收所有传入事件触发函数的额外参数。
<script>
vm.$on('test', function (msg) {
console.log(msg)
})
vm.$emit('test', 'hi')
// => "hi"
</script>