web前端 -- vue -- vue 中非父子组件通讯办法

根据千峰教育学习视频所练习的笔记 | 学习一段时间,我也有写一点东西的必要了···html

vue中除了父子组件外,还能遇到非父子组件的通讯,有如下两种方法能解决。

1. 空实例与自定义事件

  • 我先在<div>里面写两个组件,<dear-feifei><dear-zhangliuping>,这两个组件就是非父子组件的关系。如今我想在在<dear-zhangliuping>进行了一些操做,怎样能将数据传入到<dear-feifei>当中。

1.1. 先来康康大体的代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue 非父子组件通讯</title>
    <script src="../vue.js"></script>
</head>
<body>
<div id="app">
    <dear-feifei></dear-feifei>
    <dear-zhangliuping></dear-zhangliuping>
</div>
<script>
    var vm = new Vue({
        el:'#app',
        components:{
            'dear-feifei':{
                template:'<h2>{{message}}</h2>',
                data:function () {
                    return{
                        message:'hello feifei'
                    };
                },
            },
            'dear-zhangliuping':{
                template:'<ul><li v-for="item in list">{{item}}</li></ul>',
                data:function () {
                    return{
                        list:['哈哈','呵呵','吼吼']
                    };
                },
            }
        }
    });
</script>
</body>
</html>

1.2. 接着咱们来看如何来交互

  • 我须要到<dear-zhangliuping>组件中添加一个事件:
template:'<ul><li @click="getContent" v-for="item in list">{{item}}</li></ul>',
  • 而后咱们到下边写个methods添加刚才写的 getContent 方法。咱们要用这个方法获得内容,并想办法传入到<dear-feifei>里面。咱们还需在开头建立一个空实例,就能够调用这个实例的 $emit 添加自定义事件来进行触发
var busVm = new Vue(); //定义空实例
<script>
······
'dear-zhangliuping':{
    template:'<ul><li @click="getContent" v-for="item in list">{{item}}</li></ul>',
    data:function () {
        return{
            list:['哈哈','呵呵','吼吼']
        };
    },
    methods:{
        getContent:function (ev) {
            busVm.$emit('changeEvents',ev.target.innerHTML);
        }
    }
    ······
</script>

1.3. 如今已经能够发布了,但咱们怎么在另外一个组件里订阅呢?

  • 咱们能够在<dear-feifei>里面经过生命周期进行订阅,用mounted。在里面用 $on 来接收事件。
<script>
'dear-feifei':{
    template:'<h2>{{message}}</h2>',
    data:function () {
        return{
            message:'hello feifei'
        };
    },
    mounted:function () {//用于接收分发过来的数据
        busVm.$on('changeEvents',function (str) {
            console.log(str);
        });
    }
},
</script>
  • 如今点击 list 里的内容,就能看到数据能传输了:

  • 咱们如何对 message 进行修改
mounted:function () {
    busVm.$on('changeEvents',function (str) {
        console.log(str);
        this.message = str;
        <!-- this 指向busVM这个对象,要去修正,以指向dear-feifei -->
    }.bind(this));//绑定之后就指向dear-feifei了
}

  • 这样就完成了非父子组件通讯vue

    1.4. 总结:

  • 咱们先定义一个空实例,而后在想要传输数据的位置进行一个 $emit 触发
  • 在想要接收的位置,用 $on 的方式进行接收,造成一个发布与订阅的模式,来实现数据的交互,就完成了非父子组件的通讯vuex

2. vuex 状态管理

上面的方法能解决简单的项目,但稍微复杂一点的项目咱们就用vuex的方法了app

  • 我先在<div>容器里写两个组件
<div id="app">
    <div>{{count}}</div>
    <addbtn></addbtn>
    <removebtn></removebtn>
</div>
<script>
    var busVm = new Vue();
    var vm = new Vue({
        el:'#app',
        data:{
            count:0
        },
        components:{
            'addbtn':{
                template:'<button >+</button>',
            },
            'removebtn':{
                template:'<button >-</button>',
            }
        }
    });
</script>

2.1. 渲染结果就是上图这样子的啦,如今我想经过点击按钮来实现加减的处理

  • 能够发现这两个组件是共享这个 count,这个时候就涉及到非父子组件的通讯了。我能够利用 props 传输数据,而后在组件里挂载,使数据既能够传到 addbtn 中又能传到 removebtn 这两个组件中。而后再去 props 中接收 key 值
<div id="app">
    <addbtn :count="count"></addbtn>
    <removebtn :count="count"></removebtn>
</div>
<script>
components:{
    ·····
    'addbtn':{
        template:'<button >+</button>',
        props:['count'],
</script>

2.2. 那我能够添加一个方法到组件中,使得点击的时候触发一下,接着把发布功能完善

<script>
    ······
        components:{
            'addbtn':{
                template:'<button @click="setCount">+</button>',
                props:['count'],
                methods:{
                    setCount:function () {
                        busVm.$emit('changeEvents',this.count+1);
                    }
                }
            },
            'removebtn':{
                template:'<button @click="setCount">-</button>',
                props:['count'],
                methods:{
                    setCount:function () {
                        busVm.$emit('changeEvents',this.count-1);
                    }
                }
            }
        }
    });
</script>

2.3. 发布已经写好了,咱们仍是用 mounted 进行订阅

var busVm = new Vue(); //定义空实例
    var vm = new Vue({
        el:'#app',
        data:{
            count:0
        },
        mounted:function(){
            busVm.$on('changeEvents',function (num) {
                this.count = num;
            }.bind(this));
        },
  • 如今就已经完成了