categories:
- vue基础
tags: - 组件通信
父子组件通信
父子组件,嵌套一层二层
props和$emit
父组件向子组件传递数据是通过prop传递的,子组件传递数据给父组件是通过$emit触发事件来做到的
在下面的例子中,有父组件App和子组件Child
1).父组件传递了message数据给子组件,并且通过v-on绑定了一个getChildData事件来监听子组件的触发事件
2).子组件通过props得到相关的message数据,最后通过this.$emit触发getChildData事件
多级组件通信
$attrs和$listeners
第一种方式处理父子组件之间的数据传输有一个问题:如果父组件A下面有子组件B,组件B下面有组件C,这时如果组件A和组件C通信怎么办?
如果采用第一种方法,我们必须让组件A和组件B通过props传递消息,组件B再通过props和组件C通信;如果组件A和组件C之间有更多的组件,那么这种方式过于复杂了。Vue从2.4开始提供了$attrs和$listeners来解决这个问题,能够让组件A和组件C直接通信
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>$attrs和$listeners</title>
</head>
<body>
<div id="app">
<App></App>
</div>
<script src="./vue.js"></script>
<script>
Vue.component("C",{
data(){
return{}
},
template: `
<div>
<div @click="cClickHandler">{{$attrs.messagec}}</div>
</div>
`,
methods: {
cClickHandler(){
this.$emit('getCData','我是C数据')
}
}
}),
Vue.component("B",{
data(){
return{}
},
template: `
<div>
<C v-bind="$attrs" v-on="$listeners"></C>
</div>
`,
methods: {
}
}),
Vue.component("A",{
data(){
return{}
},
props:['message'],
template: `
<div>
<B v-bind="$attrs" v-on="$listeners"></B>
</div>
`,
methods: {
}
});
var App = {
data(){
return {
msg:'我是父组件',
messagec:"helloc"
}
},
template:`
<div>
<p>这是一个父组件</p>
<A :messagec="messagec" v-on:getCData="getCData"></A>
</div>
`,
methods:{
// 执行C组件的触发函数
getCData(val){
console.log(val)
}
}
};
new Vue({
el:'#app',
data(){
return{}
},
components:{
App
},
template:`
<div>
<App></App>
</div>
`
})
</script>
</body>
</html>
中央事件总线
上面两种方式处理的都是父子组件之间的数据传递,而如果两个组件不是父子关系呢?这种情况下可以使用中央事件总线的方式。新建一个Vue事件bus对象,然后通过bus.$emit触发事件,bus.$on监听触发的事件
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>$attrs和$listeners</title>
</head>
<body>
<div id="app">
<App></App>
</div>
<script src="./vue.js"></script>
<script>
// 中央事件总线
var bus = new Vue();
Vue.component('brother2',{
data(){
return{
msg: "hello brother1"
}
},
template:`
<div>
<p>我是老大</p>
<input type="text" v-model="msg" @input="passData(msg)">
</div>
`,
methods:{
passData(val){
// 触发全局事件globalEvent
bus.$emit('globalEvent',val)
}
}
});
Vue.component('brother1',{
data(){
return{
msg:"hello brother2",
brother2Msg:''
}
},
template:`
<div>
<p>我是老二</p>
<p>老大传递过来的数据:{{brother2Msg}}</p>
</div>
`,
mounted(){
// 绑定全局事件 globalEvent事件
bus.$on('globalEvent',(val)=>{
this.brother2Msg = val;
})
}
});
var App = {
data(){
return{
msg: '我是父组件对象内容',
messagec:"hello c"
}
},
methods:{
},
template:`
<div>
<brother1></brother1>
<brother2></brother2>
</div>
`,
methods:{
// 执行c组件的触发的函数
getCData(val){
console.log(val)
}
}
};
new Vue({
el:'#app',
data(){
return{}
},
components:{
App
},
template:`
<App></App>
`
})
</script>
</body>
</html>