vue -- 组件间传值

内容提要

  • 父组件 -> 子组件 (props)
  • 子组件 -> 父组件 (emit)
  • sync修饰符(在2.3.0重新被引入)
  • 同级组件间(兄弟组件)(EventBus)及EventBus被多次触发
  • vuex

正文

父组件 -> 子组件 (props)

//在子组件(Child1.vue)中:
<template>
    <div>
        //需要从父组件中获取数据的部分
        <div>{{childmsg1}}</div>  
        <div>{{childmsg2}}</div> 
    </div>
</template>
<script>
    export default {
        data() {
            return {
                ...
            }
        },
        props:['childmsg1','childmsg2'],   //可声明多个值,若为驼峰命名如childMsg在父组件中childMsg/child-msg都能被解析
        methods:{
            ...
        }
    }
</script>

//在父组件(Parent.vue)中:
<template>
    <div>
        <child1 :childmsg1='sendChild1' :childmsg2='sendChild2'></child1> 
    </div>
</template>


<script>
    import child1 from './Child1.vue';
    export default {
        data() {
            return {
                sendChild1:'我是要传给子组件的数据1',
                sendChild2:'我是要传给子组件的数据2',
            }
        },
        components:{
        	child1,
        }
    }
</script>


子组件 -> 父组件 (emit)

//在子组件(Child1.vue)中:
<template>
    <div>
        <div @click='sendMsg'>点击我向父组件发送数据</div>  
    </div>
</template>
<script>
    export default {
        methods:{
            sendMsg(){
                this.$emit('child','我是子组件传递过来的数据');
            }
        }
    }
</script>

//在父组件(Parent.vue)中:
<template>
    <div>
        <!--<child1 @child='getChildMsg'></child1> -->
        
        <component :is="'child1'" @child='getChildMsg'></component>
    </div>
</template>
<script>
    import child1 from './Child1.vue';
    export default {
        components:{
        	child1,
        },
        methods:{
            getChildMsg(res){
                console.log(res);  //'我是子组件传递过来的数据'
            }
        }
    }
</script>

sync修饰符(在2.3.0重新被引入)

一般情况下props是单向绑定的,即父组件更新了,子组件才更新,不应该在子组件中改变props。

但实际应用中我们有这个同步的需求,要解决这个问题,就用到了sync修饰符对props双向绑定。

//在子组件(Child1.vue)中:
<template>
    <div>
        <p>父组件传过来的数据为{{s1}}</p>
        <div @click="changeParent">点击</div> 
    </div>
</template>
<script>
    export default {
        props:['s1'],
        methods:{
            changeParent(){
                console.log(`父组件穿过来的数据为`+this.s1);
                this.$emit('update:s1','改变了')    //此时s1跟s1Val的值都发生了改变
            },
            
        }
    }
</script>

//在父组件(Parent.vue)中:
<template>
    <div>
        <child1 :s1.sync="s1Val"></child1> 
    </div>
</template>
<script>
    import child1 from './Child1.vue';
    export default {
        data() {
            return {
                s1Val:'syncmsg'
            }
        },
        components:{
        	child1,
        },
        
    }
</script>

同级组件间(兄弟组件)(EventBus)

1、创建文件bus.js,内容如下:

import Vue from 'vue';
export default new Vue();

2、在需要传输与接收的组件中引入:

import Bus from '../bus.js';

也可将1、2步合并在main.js中设置全局的变量,则不用在每个文件中引用,3、4照常。

window.eventbus=new Vue();

//组件中可以直接使用,如下:
created(){
    eventbus.$on('sen',this.fun)
},

3、发送数据

    sendMsg(){
        Bus.$emit('msg','我是发出的信息!');
    }

4、接收数据

created(){
    Bus.$on('msg',function(res){
        console.log(res);  //我是发出的信息!
        //若要在此处改变页面的数据,注意this的指向
    })
}

EventBus被多次触发

问题表现:就是我第一次跳转页面并触发事件的时候,控制台并没有输出。但是当我第二次再点击触发事件的时候,就会输出一个测试数据。再一次进去点击,就输出两次……依次增加了。

问题分析:当我们还在页面A的时候,页面B还没生成,也就是页面B中的created中所监听的来自于A中的事件还没有被触发。这个时候当你A中emit事件的时候,B其实是没有监听到的。

当你从页面A到页面B跳转的时候,发生了什么?首先是先B组件先created然后beforeMount接着A组件才被销毁,A组件才执行beforeDestory,以及destoryed.

解决方案:我们可以把A页面组件中的emit事件写在beforeDestory中去。因为这个时候,B页面组件已经被created了,也就是我们写的$on事件已经触发了。

//A组件中:
beforeDestroy () {
    Bus.$emit('sen','hello!');
}

//B组件中:
methods:{
    fun(res){
        console.log(res);
    }
},
created(){
    Bus.$on('sen',this.fun);
},

//这段代码恢复紧接着下一条问题
beforeDestroy () {
    Bus.$off('sen', this.fun);
},

此时我们又发现了新的问题:虽然第一次有了数据,但是之后还是有依次增加的问题。

原因:$on事件是不会自动清楚销毁的,需要我们手动来销毁。

解决方案:在B组件页面中添加Bus.$off来关闭。

小结:如果想要用EventBus来进行页面组件之间的数据传递,需要注意两点:

1、组件A中$emit事件应在beforeDestory生命周期内。

2、组件B内的$on记得要销毁。

Vuex

Vuex 是一个专为 Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

如果不打算开发大型单页应用,使用Vuex可能是繁琐冗余的。使用上面的方法可以满足大多需求,所以这篇先不讲了,下篇见~

posted @ 2018-03-17 22:00  adoctors  阅读(206)  评论(0编辑  收藏  举报