vue2.0 组件通信的三种方式(父子通信,子父通信,中央事件总线)

Vue3 正式版快要发布了,扶我起来,我还能学 /(ㄒoㄒ)/~~

今天整理学习笔记,发现过去写的一篇Vue2.0组件传值文章还算工整。虽然有点过时了,但毕竟 Vue2 一时半会还是主流,组件通信也是vue2最常用的技术之一,对初学者多少有点帮助。放着也是放着,发出来刷刷存在感~

下面开始正文。

这里具体介绍三种组件通信场景:父子通信,子父通信,兄弟组件通信(中央事件总线)

父子通信

  1. 父组件里定义数据 users,并给导入的子组件绑定数据 users;

  2. 子组件里用 props 选项获取父组件绑定给子组件的数据 users,并在 template 中直接使用数据 users。

<!-- App.vue 父组件 -->
<template>
    <div id="app">
        <!-- 2. 导入子组件 Users.vue,并绑定 data 中的数据 users -->
        <users v-bind:users='users'></users>
    </div>
</template>
<script>
    // 导入子组件
    import Users from './components/Users'
    
    export default {
        name: 'app',
        data () {
            return{
                // 1. 定义数据 users
                users:[
                    {name:'zs',age:19,gender:'male'},
                    {name:'ls',age:21,gender:'male'},
                    {name:'ww',age:23,gender:'female'}
                ]
            }
        }
    }
</script>
<!-- Users.vue 子组件 -->
<template>
    <div id="users">
        <h3>用户列表</h3>
        <!-- 4. 直接使用数据 users -->
        <ul v-for="user in users">
        	<li>用户名:{{user.name}},年龄:{{user.age}},性别:{{user.gender}}</li>
    	</ul>
    </div>
</template>

<script>
    export default {
        name: 'users',
        // 3. 用 props 选项获取父组件绑定给子组件的数据 users
        props: {
            users: {
                type: Array,
                required: true
            }
        }
    }
</script>

子父通信

场景:在子组件里调用 changeTitle() 方法,改变父组件数据 title 的值,同时改变。

思路:使用事件从子组件向父组件传值。

  1. 在子组件中自定义函数 changeTitle,调用该函数会触发事件 titleChanged,该事件会传一个参数”新的标题“;
  2. 当点击子组件的 header 标签时,调用自定义函数 changeTitle,触发了 titleChanged;
  3. 父组件中自定义函数 updateTitle(newTitle),该函数的参数来自于子组件触发事件 titleChanged 传入的参数 “新的标题”,并把"新的标题" 赋值给父组件 data 里的数据 title;
  4. 父组件 template 里导入子组件,
  5. <app-header> 绑定子组件的 titleChanged($event) 事件,该事件调用父组件函数 updateTitle(newTitle);
  6. <app-header> 绑定父组件 data 里的数据 title,此时 title 已经变成了子组件传入的"新的标题"
<!-- App.vue 父组件 -->
<template>
    <div id="app">
        <!-- 3. 导入子组件 Header.vue,绑定子组件的自定义事件 titleChanged,该事件触发 updateTitle() 方法,该方法接收自定义事件 titleChanged 传入父组件的参数 "新的标题",用 $event 表示;
		5. 子组件绑定父组件 data 中的数据 title,此时 title 的值已经是"新的标题" -->
        <app-header @titleChanged="updateTitle($event)" :title='title'></app-header>
    </div>
</template>
<script>
    import Header = from './components/Header'
    
    export default {
        name: 'app',
        data () {
            return{
                title:'旧的标题',
                users:[
                    {name:'zs',age:19,gender:'male'},
                    {name:'ww',age:23,gender:'female'}
                ]
            }
        },
        methods:{
        	// 4. 自定义 updateTitle() 方法,使旧的标题变成新的标题
        	updateTitle(newTitle){
                // newTitle是子组件传到父组件的参数 "新的标题"
                this.title = newTitle;
            }
    	},
        components:{
            // 将 Header.vue 组件命名为 app-header
            "app-header":Header
        }
    }
</script>
<!-- Header.vue 子组件 -->
<template>
	<!-- 2. 点击子组件的 header 标签时,触发 changeTitle 方法 -->
    <header @click="changeTitle">
        <h1>{{title}}</h1>
    </header>
</template>

<script>
    export default {
        name: 'app-header',
        props:{
            title:{
                type: String
            }  
        },
        methods: {
            // 1. 自定义 changeTitle 方法
            changeTitle(){
                // 自定义事件 titleChanged,该事件会传一个参数 "新的标题"
                this.$emit("titleChanged","新的标题")
            }
        }
    }
</script>

兄弟组件通信(中央事件总线)

  1. 创建中央事件总线
    middleBus.js
import Vue from 'Vue'

export default new Vue;
  1. 创建组件一,引入中央事件总线,$emit实例方法触发自定义的addMsg方法,并传参
    child1.js
<script>
import middleBus from '../middleBus.js';
export default {
    methods: {
        sendMsg: function(){
            middleBus.$emit('addMsg','这条消息来自child1.js')
        }
    }
    
}
</script>
  1. 创建组件二,引入中央事件总线,$on实例方法监听自定义的addMsg方法,并把传过来的参数传递给 $on监听器的回调函数
    child2.js
<script>
import middleBus from '../middleBus.js';
export default {
    data(){
        return {
            msg:""
        }
    }
    created: {
        middleBus.$on('addMsg', function(e){
            console.log('e') // 这条消息来自child1.js
            this.msg = e
        }
    }
    
}
</script>
  1. 卸载页面前,移除事件监听器,$off(‘监听的事件名’)实例方法移除addMsg事件。否则会重复发射事件
    child2.js
<script>
export default {
    data(){
        return {
            msg:""
        }
    }
    created:{
        sendMsg: function(){
            middleBus.$on('addMsg', function(e){
                console.log('e')    // 这条消息来自child1.js
                this.msg = e
            }
        }
    },
    beforeDestroy(){
        middleBus.$off('addMsg')
    }
}
</script>

附注

其实用到中央事件总线,数据通信就已经有点复杂了,组件频繁加载的情况下,很容易造成事件重复注册。如果没有及时销毁事件,会造成很多意想不到的bug,所以更推荐用vuex进行全局状态管理。这就是 Vue2 另一个必知必会技能了,还没有掌握的小伙伴快去学习吧~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值