vuex和event-bus有什么不同

我们都知道,vuex 的底层实现原理其实就是 event-bus,那么它和普通的 event-bus 有什么不同呢?我们通过简单的源码一步步实现来搞懂这个问题。
event-bus
首先一个普通的 event-bus 是这样的:
// main.js
Vue.prototype.$bus = new Vue();

// 组件中
this.$bus.$on('console', (text) => {
    console.log(text);
});

// 组件中
this.$bus.$emit('console', 'hello world');

它是通过 Vue 的$on和$emit api 来传递消息的。
vuex 的响应式数据
而 vuex 的数据是响应式的,那么我们首先实现这种响应式数据:

class store {
    constructor(options) {
        this.vm = new Vue({
            data: {
                state: options.state
            },
        });
    }

    get state() {
        return this.vm.state;
    }
}

注意,上面的data不是一个函数,因为这里我们只会实例化一次。然后我们通过添加一个 state 的 getter 方法来暴露内部的 event-bus 的 state 属性。

那怎么实现响应式的呢?因为在实例化 vm 的时候,Vue 会自己使用 defineReactive 把 data 变为响应式数据,从而会收集有关它的依赖,然后在自己变动的时候,通知依赖更新。
加上 getters
vuex支持加上 getters,怎么加呢?直接初始化一个 getters 属性即可:

class store {
    constructor(options) {
        this.vm = new Vue({
            data: {
                state: options.state
            },
        });

        const getters = options.getter || {};
        this.getters = {};
        Object.keys(getters).forEach((key) => {
            Object.defineProperty(this.getters, key, () => {
                get: () => getters[key](this.state)
            })
        });
    }

    get state() {
        return this.vm.state;
    }
}
加上 mutations
类似的,我们可以添加一个 mutations 属性来保存 mutations,然后实现一个 commit 方法,在调用 commit 方法的时候去 mutations 里面找,然后调用相应函数即可:

class store {
    constructor(options) {
        this.vm = new Vue({
            data: {
                state: options.state
            },
        });

        const getters = options.getters || {};
        this.getters = {};
        Object.keys(getters).forEach((key) => {
            Object.defineProperty(this.getters, key, () => {
                get: () => getters[key](this.state)
            })
        });

        const mutations = options.mutations || {};
        this.mutations = {};
        Object.keys(getters).forEach((key) => {
            this.mutations[key] = (args) => mutations[key](state, args);
        });
    }

    get state() {
        return this.vm.state;
    }

    commit(name, args) {
        this.mutations[name](args);
    }
}
加上 actions
类似的,我们可以添加一个 actions 属性来保存 actions,然后实现一个 dispatch 方法,在调用 dispatch 方法的时候去 actions 里面找,然后调用相应函数即可。不过稍有不同的是,actions 里面的方法和 mutations 里面的方法的第一个参数不同,它要传整个 store 进去,因为不仅要获得 state,还需要在里面调用 commit 方法:

class store {
    constructor(options) {
        this.vm = new Vue({
            data: {
                state: options.state
            },
        });

        const getters = options.getters || {};
        this.getters = {};
        Object.keys(getters).forEach((key) => {
            Object.defineProperty(this.getters, key, () => {
                get: () => getters[key](this.state)
            })
        });

        const mutations = options.mutations || {};
        this.mutations = {};
        Object.keys(mutations).forEach((key) => {
            this.mutations[key] = (args) => mutations[key](state, args);
        });

        const actions = options.actions || {};
        this.actions = {};
        Object.keys(actions).forEach((key) => {
            this.actions[key] = (args) => actions[key](this, args);
        });
    }

    get state() {
        return this.vm.state;
    }

    commit(name, args) {
        this.mutations[name](args);
    }

    dispatch(name, args) {
        this.actions[name](args);
    }
}
其它
后面install流程就和其它插件的install流程差不多一样了,唯一需要注意的是插入到 beforeCreate 钩子里面的代码,它是通过获取父级的 store 来获取全局 store 的。

可以看到,vuex 和传统的 event-bus 的不同点除了 vuex 实现了更加友好的响应式状态之外,还禁止了 vuex 里面数据的直接修改,大大增强了信任度(有点像promise的status),通过增加 mutations 和 actions 这种“中间层”,它能更好的控制中间的变化,比如实现时间旅行、状态回退和状态保存的功能。

另外,需要说明的是,mutation 和 action 的不同点不仅在于 mutation 里面只能写同步代码,action 里面只能写异步代码,还在于 mutation 里面的方法的第一个参数是state(因为只需要修改 state 就可以了),而 action 里面的方法的第一个参数是store(因为还需要调用 commit 方法)
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Vue.js Event Bus 是一种用于在组件之间进行通信的模式,它可以实现组件间的数据共享。 Event Bus 是一个全局的 Vue 实例,它可以作为央事件总线来传递事件和数据。可以使用 Vue 的 `prototype` 属性来定义一个全局的 Event Bus,例如: ```js // 定义全局的 Event Bus Vue.prototype.$bus = new Vue() // 在组件使用 Event Bus this.$bus.$emit('event-name', data) this.$bus.$on('event-name', handler) ``` 在上面的例子,定义了一个全局的 Event Bus,并使用 `$emit` 方法来触发一个自定义事件,并传递数据 `data` 给事件处理函数。同时,使用 `$on` 方法来监听这个自定义事件,并指定一个事件处理函数 `handler` 来处理事件。 可以在多个组件使用 Event Bus 来实现数据共享,例如: ```js // 组件 A this.$bus.$emit('update-name', 'new name') // 组件 B this.$bus.$on('update-name', function(name) { this.name = name }) ``` 在上面的例子,组件 A 使用 Event Bus 触发一个名为 `update-name` 的自定义事件,并传递一个新的名字 `'new name'`。组件 B 监听这个事件,并在事件处理函数将 `name` 属性更新为新的名字。 需要注意的是,使用 Event Bus 可以实现组件之间的数据共享,但也容易造成代码的混乱和难以维护。因此,在使用 Event Bus 时,应该遵循一些规范和最佳实践,例如: - 明确事件的名称和数据类型,以避免出现名称冲突和数据类型不一致的问题。 - 在组件销毁时,应该及时取消对事件的监听,以避免内存泄漏。 - 不要滥用 Event Bus,应该使用其他更合适的方式(如 Vuex)来进行数据共享。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你说的誓言°变失言

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值