使用全局 bus 在 Vue 的兄弟组件中简单传值(以及 this 重定向的 5 种方法)

总线传值有两种写法:原型 bus 写法【 window.Vue.prototype.bus = new Vue () 】、全局 bus 写法【 window.bus=new Vue () 】。
如果使用了原型写法,那在组件里面必须使用 this.bus.$emit () 发送消息,以及使用 this.bus.$on () 接收消息。它们全部要用 this 开头。如果使用了全局写法,则可以简化为 bus.$emit () 及 bus.$on () 了。

在确保全局 bus 不会发生变量名称冲突的前提下,使用全局 bus 的写法要更简单一些。首先,修改 resources\assets\js\app.js 文件引入全局 bus

require('./bootstrap');
window.Vue = require('vue');
window.bus=new Vue();   //全局bus
// window.Vue.prototype.bus = new Vue();   //原型bus
import ...
const app = new Vue({
    el: '#app',
    components:{
        ...
    },
});

这里需要注意的是 window.bus=new Vue () 这行代码的位置有讲究,不能把它放在 const app=new Vue ({...}); 之后。

在 blade 模板中,以下两个 Vue 组件是同级关系

<cart-items :items="{{$cartItems}}" ></cart-items>
<cart-selected></cart-selected>

file
组件 1 的作用:
1、接收数据库查询到的复杂对象 $cartItems
2、根据用户的勾选或删除等操作进行加工处理,得到特定数据 data
3、加工完毕,发送一个消息 msg_SelectedItemChange 并对外传递数据 data
组件 1 发送数据的代码很简单,只需一行
bus.$emit('msg_SelectedItemChange', data)

组件 2 的作用:
1、接收组件 1 加工后的数据 data
2、将此数据刷新到浏览器里(或者等待用户点击提交按钮发送 ajax 请求等等)
组件 2 接收数据稍微麻烦一点,因为需要使用一个回调函数,大致如下
bus.$on('msg_SelectedItemChange', 回调函数的名称)

难点在于回调函数内部的 this 指向可能有问题,比如下面的写法就不能在浏览器里面显示组件 2 获取的数据

<template>
    <div>组件2{{cartItems}}</div>
</template>
<script>
    export default {
        name: "CartSelected",
        data(){
            return{
                cartItems:[],
            }
        },
        mounted(){
            bus.$on('msg_SelectedItemChange', function(data){
                this.cartItems=data;    //无效,因为this指向的已经不是本组件了!
            })
        },
    }
</script>

尝试使用 call () 重定向回调函数内部的 this 指向也是无效的

        mounted(){
            bus.$on.call(this, 'msg_SelectedItemChange', function(data){
                this.cartItems=data;    //也无效
            })
        },

改用 that 重定向,有效!

        mounted(){
            let that=this;
            bus.$on('msg_SelectedItemChange', function(data){
                that.cartItems=data;    //有效,匿名函数使用that重定向到本组件
            })
        },

改用立即执行函数并返回一个闭包函数的写法也是有效的,可惜晦涩得很,写起来也麻烦。闭包函数既能访问形参 it 又能访问 that 变量,使用任何一个都可以完成任务,唯独不能使用 this

        mounted(){
            let that=this;
            bus.$on('msg_SelectedItemChange', function(it){
                return function(data){
                    that.cartItems=data;    // OK
                    it.cartItems=data;      // OK too
                    this.cartItems=data;    // Bad
                }
            }(this))
        },

使用 bind 重定向(很简洁的写法)
虽然 that 重定向的写法也很简洁,但是函数体里面的 this 必须全部改用 that 替换。使用 bind 则无需替换,刚好解决了这一缺陷。

        mounted(){
            bus.$on('msg_SelectedItemChange', function(data){
                this.cartItems=data;
            }.bind(this))
        },

也可以采用一种很标准的写法(往 methods 对象里面插入一个新方法)。此法不够简洁,但是比较灵活,可以随时调用 refresh () 方法。

        methods:{
            refresh(data){
                this.cartItems=data;
            }
        },
        mounted(){
            bus.$on('msg_SelectedItemChange', this.refresh)
        },

下面是第 5 种,使用箭头函数的写法(比 bind 还要简洁)

        mounted(){
            bus.$on('msg_SelectedItemChange', data=>
                this.cartItems=data
            )
        },
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
未填写
文章
68
粉丝
17
喜欢
141
收藏
119
排名:130
访问:7.5 万
私信
所有博文
社区赞助商