非父子组件间的通信:中央事件总线、父链、子组件索引

<!DOCTYPE html>
<html>
<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>Document</title>
    <script src="Vue.2.6.10.js"></script>
</head>
<body>
    <div id="app1">
        {{ message }}
        <!-- <component-01 :is="component-01"></component-01>????? -->
        <component-01 ></component-01>
    </div>
    <div id="app2">
        {{ message }}
        <component-02></component-02>
    </div>
    <div id="app3">
        <button @click = "handleRef">A</button>
        <!-- <button @click = "handleRef">B</button>
        <button @click = "handleRef">C</button> -->
        {{ message }}
        <component-a ref="comA" ></component-a>
        <!-- <component-b ref="comB" ></component-b>
        <component-c ref="comC" ></component-c> -->
    </div>
    <br>
    <!-- 并不能通过上面那种方式动态切换组件 试试这个 -->
    <div id="app4">
        <button @click="com = 'comA'">comA</button>
        <button @click="com = 'comB'">comB</button>
        <button @click="com = 'comC'">comC</button>
        <div :is = "com"></div>
        <component :is="com"></component>
    </div>
</body>
<script>
    //在Vue2.X中,推荐使用一个空的中央事件总线bus,即一个中介(类似于连接租房者与房东的房屋中介)
    var bus = new Vue();
    Vue.component('component-01',{
        template:'<button @click="handleEvent" >传递事件</button>',
        methods: {
            handleEvent:function(){
                bus.$emit('on-message','该内容来自组件01');
            }
        },
    });
    // 在app1初始化时,即在生命周期mounted钩子里监听(持续监听?)来自bus的事件,
    // 而在组件01中点击按钮会通过bus将这个事件传递出去
    var app1 = new Vue({
        el:"#app1",
        data:{
            message:''
        },
        mounted() {
            var _this = this;//在一个代码片段里this有可能代表不同的对象,而编码者希望_this代表最初的对象
            //在实例初始化时监听来自bus实例的事件
            bus.$on('on-message',function(msg){
                _this.message = msg;
            })
        },
    });

    Vue.component('component-02',{
        template:'<button @click="handleEvent">通过父链直接修改数据</button>',
        methods:{
            handleEvent:function(){
                //访问到父链后可以进行任何操作,包括修改父组件数据等
                this.$parent.message = '来自组件02的内容';
                // 虽然这种操作能够实现,但事实上子组件应该避免依赖父组件的数据,更不应该去修改(应该缓存一份?)
                //父子组件最好通过props和$emit来通信
                console.log(this.$parent);//懂了!是整个Vue(app2)实例!
            }
        }
    });
    var app2 = new Vue({
       el:"#app2",
       data:{
           message:''
       },
    });

    Vue.component('component-a',{
        template:'<div>子组件A</div>',
        data() {
            return {
                message:'来自子组件A!'
            }
        },
    });
    var app3 = new Vue({
       el:"#app3",
       data:{
           message:'',
       },
       methods:{
            handleRef:function(){
                console.log(
                    this,
                    this.$refs,
                    this.$refs["comA"],
                    this.$refs["comA"].message
                    //this.$refs.comA是错误的写法  // NaN?
                    //因在组件渲染完成后再填充?
                );
                this.message = this.$refs["comA"].message;
            }
       },
       mounted(){
           console.log(this.$children);
       } 
    });


    Vue.component('comA',{
        template:'<div>子组件A</div>',
       
    });
    Vue.component('comB',{
        template:'<div>子组件B</div>',
        
    });
    Vue.component('comC',{
        template:'<div>子组件C</div>',
        
    });
    var app4 = new Vue({
       el:"#app4" ,
       data:{
           com:'comA'
       }
    });
</script>
</html>

 

posted @ 2019-05-21 17:58  林不渡  阅读(238)  评论(0编辑  收藏  举报