Fork me on GitHub

父子组件通信

父子组件,嵌套一层二层
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>
posted on 2020-01-16 19:57  anyux  阅读(127)  评论(0编辑  收藏  举报