没有Vue的computed,独立JS文件怎么使用和监听VuexStore数据

1,915 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

代码最小粒度不在Vue组件,在JS文件

可能有人会奇怪,代码不都写在Vue组件里面,为什么还要在JS文件使用Vuex数据状态?

不是的,因为随着项目的规模越来越大,职责划分变得尤为重要,不能把所有代码都写在Vue组件中。代码最小划分粒度,可能会是一个个独立的JS文件,通过标准的ESModule来彼此衔接和应用。

业务背景

Vuex Store的auth模块下,有个authorized状态,用来标识WebSocket连接是否建立且授权通过。

之所以这个标识维护在Vuex,是因为页面需要通过一个图标显示通信是否正常,且允许手动点击来关闭WebSocket连接。

  • store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

import auth from './modules/auth'

Vue.use(Vuex)

const store = new Vuex.Store({
    modules: {
        auth,
    },
})

export default store
  • store/modules/auth.js
export default {
    namespaced: true,
    state: {
        authorized: false,  // 标识
    },
    mutations: {
        SET_AUTH(state, authorized) {
            state.authorized = authorized
        },
    },
}

同时,有一个neffos.js文件负责进行WebSocket连接,需要引用authorized状态,每当send()方法被调用发送数据时,先要判断authorized为true才发送,否则收集进入消息队列。

还要监听authorized重新为true时,遍历消息队列,依次推送消息。

  • websocket/neffos.js
import store from '@store'
const queue = []

// 监听authorized为true时,发送消息队列
// if (authorized) {
//     while (queue.length > 0) {
//         const msg = queue[0]
//         this.nsConn.emit('message', msg)
//         queue.shift()
//         console.log('queue emit', msg)
//     }
// }


/*
 * 发送信息
 */
send(commandKey, data) {
    const msg = JSON.stringify(commandKey, data)
    // 将标识放在方法体内,每次调用都获取最新的
    const { authorized } = store.state.auth

    if (authorized && this.nsConn) {
        this.nsConn.emit('message', msg)
        console.info('neffos send', msg)
    } else {
        queue.push(msg)
    }
}

问题描述

如果上述代码在Vue组件中,一切都好办,我们可以把authorized挂载到computed中,还可以通过watch来监听数据的变化。

但是WebSocket只负责通信事宜,和视图无关的,理应封装在独立js文件,这样后期还可以迁移到jQuery或者React项目。

而问题就在于,将store.state赋值给独立js文件中的变量,是不具备响应式的,且无法监听它是否发生了变化。

思路1:借助EvenBus进行通知(不推荐)

  • store/modules/auth.js
// 引入事件总栈
import EventBus from '@event-bus'

export default {
    namespaced: true,
    state: {
        authorized: false,
    },
    mutations: {
        SET_AUTH(state, authorized) {
            state.authorized = authorized
            // 当赋值为true时,发送通知
            if(authorized){
                EventBus.emit('authSuccess')
            }
        },
    },
}
  • websocket/neffos.js
import store from '@store'
import EventBus from '@event-bus'

const queue = []

// 监听authorized为true时,发送消息队列
EventBus.on('authSuccess', () => {
    while (queue.length > 0) {
        const msg = queue[0]
        this.nsConn.emit('message', msg)
        queue.shift()
        console.log('queue emit', msg)
    }
})

思路2:Store.watch监听(推荐)

其实Vuex Store实例本身就提供了watch方法,用于监听state或者getters数据的变化。这样就不用增加EventBus的订阅,少写代码减少程序的复杂度,也让逻辑更清晰。

  • websocket/neffos.js
import store from '@store'
import EventBus from '@event-bus'

const queue = []

// 监听authorized为true时,发送消息队列
store.watch(
    // 第一个参数是箭头函数,用来选择你要监听的数据
    (state,getters) => state.auth.authorized,
    // 第二参数也是箭头函数,是数据改变后的回调监听
    authorized => {
        if (authorized) {
            while (queue.length > 0) {
                // 发一个删一个,确保发送顺序
                const msg = queue[0]
                this.nsConn.emit('message', msg)
                queue.shift()
                console.log('queue emit', msg)
            }
        }
    },
)

参考