Vue组件间通信

1,457 阅读2分钟

前言

父子组件通信

1、使用props和$emit父子组件相互通信;
2、父组件$children操作子组件;
3、子组件$parent访问父组件;

非父子组件通信

1、使用中间事件总线(eventbus)来处理非父子组件间的通信;
2、祖先元素通过provide提供数据,后代通过inject获取该数据;
3、使用$attrs和$listenerss实现祖孙组件通信;
4、$root直接访问根组件;

接下来介绍下非父子组件通信中的Event Bus和Provide Inject

Event Bus

效果图

直接撸代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Event Bus 组件通信</title>
    <script src="../node_modules/vue/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <com-a></com-a>
        <com-b></com-b>
        <com-c></com-c>
    </div>
    <template id="coma">
        <div>
            <h3>A组件:{{msg}}</h3>
            <button @click="sendToC">A将msg发送给C组件</button>
        </div>
    </template>
    <template id="comb">
        <div>
            <h3>B组件:{{msg}}</h3>
            <button @click="sendToC">B将msg发送给C组件</button>
        </div>
    </template>
    <template id="comc">
        <div>
            <h3>C组件:{{msg}}</h3>                   
        </div>
    </template>
   <script>
       //中央事件总线
       var Event = new Vue();
       var A= {
           template:'#coma',
           data(){
               return {
                   msg:'A传递给C的msg'
               }
           },
           methods:{
               sendToC(){
                   Event.$emit('data-a',this.msg);
               }
           }
       };
       var B= {
           template:'#comb',
           data(){
               return {
                   msg:'B传递给C的msg'
               }
           },
           methods:{
               sendToC(){
                   Event.$emit('data-b',this.msg);
               }
           }
       };
       var C= {
           template:'#comc',
           data(){
               return {
                   msg:''
               }
           },  
           mounted(){
               Event.$on('data-a',msg=>{
                   this.msg = msg;
               });
               Event.$on('data-b',msg=>{
                   this.msg = msg;
               })
           }         
       };
       let vm = new Vue({
           el:'#app',
           components:{
               'com-a':A,
               'com-b':B,
               'com-c':C
           }
       });
   </script> 
</body>
</html>

provide inject

效果图

代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>provide--inject组件通信方式</title>
    <script src="../node_modules/vue/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <h1>
            {{projectName}}
            <br/>
            {{appName}}
            <br/>
            {{timeFlag}}
            <br/>
        </h1>
        <Parent/>
    </div>
    <script>
        const Child = {
            inject:['appName','projectName'],
            template:`<div>
                {{projectName}}
                <br/>
                {{appName}}此时Parent修改了appName
                </div>`
        };
        const Parent = {
            inject:['appName','timeFlag','projectName'],
            provide(){
                return{
                    appName:this.appName + '父级接收上级传来数据处理后的appName',
                }
            },
            components:{
                Child,
            },
            template:`<div>                
                {{projectName}}
                <br/>
                {{appName}}
                <br/>
                {{timeFlag}}
                <br/>
                <Child/>
                </div>`
        }
        const projectName = '跨级组件通信';
        let vm = new Vue({
            el:'#app',
            components:{
                Parent
            },
            provide(){
                return{
                    projectName:this.projectName,
                    appName:this.appName,
                    timeFlag:this.timeFlag
                }
            },
            data:{
                
                    projectName,
                    appName:'这是app名称',
                    now:Date.now()
                
            },
            computed:{
                timeFlag(){
                    return this.now;
                }
            },
            created(){
                setInterval(()=>{
                    this.now = Date.now();
                },1000)
            }
        });
    </script>
</body>
</html>

注意:provide inject方式的组件通信数据是非响应式的