除了父子之间通信还有兄弟组件通信或跨级通信等
在Vue2 中,一般都使用一个空的vue实例作为中央事件总栈来处理,
这里的“中央事件总栈”就类似于我们生活中“中介”一样的存在;
比如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
#v1{
/*display: none;*/
width:200px;
margin: 100px;
border: 2px solid #faf;
}
</style>
</head>
<body>
<div id="v1">
<v-component></v-component>
<p>{{ val }}</p>
</div>
<script src="vue.min.js"></script>
<script>
//先在这里创建一个空的vue实例
var bus=new Vue({});
//定义全局组件
Vue.component("v-component",{
template:'<button @click="postData">传输数据</button>',
methods:{
postData:function () {
bus.$emit('message','通过组件传递的数据');
}
}
});
//最后创建实例app
var app=new Vue({
el:"#v1",
data:{
val:''
},
//这里使用生命周期的钩子mounted,在这里可以监听到来自中央事件总栈的信息,通过组件中的按钮发布事件,
//app收到后在回调里完成对应的业务逻辑
mounted:function () {
var that=this;
//监听来自bus实例的事件
bus.$on('message',function (msg) {
that.val=msg;
})
}
})
</script>
</body>
</html>
实现效果:
除了中央事件总栈外,还可以通过 父链 和 子组件索引 来完成通信:
父链:
在子组件中,用this.$parent可以直接访问该组件的父实例及组件
在父组件中,用this.$children访问其所有的子组件,并且是可以无限向上或向下递归访问,直到“根实例”或“最内层组件”
<body>
<div id="v1">
<v-component></v-component>
<p>{{ val }}</p>
</div>
<script src="vue.min.js"></script>
<script>
Vue.component("v-component",{
template:'<button @click="postData">通过父链修改数据</button>',
methods:{
postData:function () {
this.$parent.val='通过组件传递的数据';
}
}
});
//最后创建实例app
var app=new Vue({
el:"#v1",
data:{
val:''
}
})
</script>
</body>
其实在项目中,一般尽量不要用子组件主动修改父组件的数据,理想情况下,只有组件自己能修改自己的状态,父子还是推荐 $emit 和 props来通信最好;
子组件索引
当子组件较多时,建议使用vue提供的子组件索引,用特殊的属性ref 为子组件指定一个索引名称。
在父组件模板中,子组件标签上使用ref指定一个名称,并在父组件内通过this.$refs访问指定名称的子组件。
例如:
<body>
<div id="v1">
<button @click="setRef">获取子组件内容</button>
<v-component ref="comA"></v-component>
<p>{{ val }}</p>
</div>
<script src="vue.min.js"></script>
<script>
Vue.component("v-component",{
template:'<p>我是子组件</p>',
data:function () {
return {
msg:"我的内容"
}
}
});
var app=new Vue({
el:"#v1",
data:{
val:""
},
methods:{
setRef:function () {
var i=this.$refs.comA.msg;
this.val=i;
}
}
})
</script>
</body>
显示效果:
需要注意的是: $refs只在组件渲染完成后才填充,不是响应式,尽量不要在计算属性中使用