zoukankan      html  css  js  c++  java
  • web前端 -- vue -- vue 中非父子组件通信办法

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

    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 里的内容,就能看到数据能传输了:
    ![](https://img2018.cnblogs.com/blog/1817586/201910/1817586-20191027151302554-917636597.png)
    • 我们如何对 message 进行修改
    mounted:function () {
        busVm.$on('changeEvents',function (str) {
            console.log(str);
            this.message = str;
            <!-- this 指向busVM这个对象,要去修正,以指向dear-feifei -->
        }.bind(this));//绑定以后就指向dear-feifei了
    }
    
    ![](https://img2018.cnblogs.com/blog/1817586/201910/1817586-20191027152225134-1486208214.png)
    • 这样就完成了非父子组件通信

    1.4. 总结:

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

    2. vuex 状态管理

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

    • 我先在<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>
    
    ![](https://img2018.cnblogs.com/blog/1817586/201910/1817586-20191027152237578-1164821315.png)

    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));
            },
    
    • 现在就已经完成了
    ![](https://img2018.cnblogs.com/blog/1817586/201910/1817586-20191027152255054-328411813.png)
  • 相关阅读:
    把一列数据分割成两列
    数据校验,轴的概念
    叠加折线图
    饼图
    柱状图、水平柱状图
    柱状图
    数据筛选过滤
    余数
    输出进度条
    生成器-文件内容
  • 原文地址:https://www.cnblogs.com/hefeifei/p/11747685.html
Copyright © 2011-2022 走看看