命名空间-namespaced
在前端的知识体系中,命名空间的概念或许你或多或少都有听说过,本章讲解一下 Vuex 中的命名空间的作用。
相信各位对 Vuex 都很熟了,我们经常拿它来作数据共享,但由于 Vuex 使用的是单一的状态管理模式,
所有状态都会挂载到一个对象(store)上。但随着我们项目中业务的增多,store 对象可能变得非常庞大和臃肿,致使我们的维护是非常复杂和麻烦的。
因此,Vuex 出现了模块的概念,它允许我们对 store 对象进行切割,划分成一个一个小模块,每个模块都拥有自己的 state 、 mutations 、 actions 与 getters。在默认情况下,模块内部的 mutations 、 actions 与 getters 是全局注册。
什么意思呢?我们来看看下面的 user.js 模块:
// store/modules/user.js
export default {
state: {
name: '橙某人',
},
mutations: {
setName(state, newName) {
state.name = newName;
}
},
actions: {
updateName({ commit }, newName) {
setTimeout(() => {
commit('setName', newName)
}, 3000)
}
},
getters: {
getName: (state) => state.name
}
}
引入:
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
Vue.use(Vuex)
export default new Vuex.Store({
state: {},
mutations: {
setName() {
console.log('俺也会被触发-setName');
}
},
actions: {},
getters: {},
modules: { user }
})
在具体业务中使用:
this.$store.commit('setName', 'ydydydq');
// this.$store.dispatch('updateName', 'ydydyd');
// let name = this.$store.getters.getName;
上面的例子中,你会发现两个 setName() 方法都被触发了,这并不是我们想看到的,当我们项目模块很多时,就容易发现重名事件,这种场景就非常容易发生!
那我们如何来解决这个问题呢?Vuex 引入命名空间的概念,我们仅仅需要在模块中添加 namespaced 属性即可:
// store/modules/user.js
export default {
namespaced: true, // 模块开启命名空间
state: {
name: '橙某人',
},
mutations: {
setName(state, newName) {
state.name = newName;
}
},
...
}
具体业务使用:
this.$store.commit('user/setName', 'ydydydq');
// this.$store.dispatch('user/updateName', 'ydydyd');
// let name = this.$store.getters['user/getName'];
是不是非常的简单?(✪ω✪) 当然有个需要注意的点,就是模块中的 state 默认嵌套了命名空间的, 所以开不开启模块的命名空间对 state 是没有影响的。
let name = this.$store.state.user.name;
插件-plugins
说起 Vuex 可能我们首先都会记得它有五个核心概念,state 、 mutations 、 actions 、 getters 和 modules,但其实它还有一些内容也是挺重要,像 map 辅助函数、注册动态模块(registerModule)和插件(plugins)等等。
接下来,我们就来看看 plugins 的使用方式和作用场景。
它的使用很简单:
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import indexPlugin from './plugins/index'
Vue.use(Vuex)
export default new Vuex.Store({
state: {},
mutations: {},
actions: {},
getters: {},
modules: {},
plugins: [indexPlugin]
})
Vuex 的插件就是一个函数,它接收 store 作为唯一参数:
// store/plugins/index
export default function createIndexPlugin(store) {
console.log(store); // store为整个Vuex实例, 会在初始化的时候调用
store.subscribe((mutation, state) => {
// 每次 mutation 之后调用, 也就是你每次调用 this.$store.commit() 会触发
console.log(mutation, state);
})
}
以上就是它的基本使用,至于它的作用场景,小编总结这三点内容。
数据同步
// socket是与服务端建立长链接实例
const plugin = createWebSocketPlugin(socket);
const store = new Vuex.Store({
state,
mutations,
plugins: [plugin]
})
export default function createWebSocketPlugin (socket) {
return store => {
// 服务端通知时触发
socket.on('data', data => {
store.commit('receiveData', data) // 同步到本地
})
store.subscribe(mutation => {
if (mutation.type === 'UPDATE_DATA') {
socket.emit('update', mutation.payload) // 同步到服务端
}
})
}
}
生成快照
const myPluginWithSnapshot = store => {
// 把初始化的state进行一次深拷贝
let prevState = _.cloneDeep(store.state)
store.subscribe((mutation, state) => {
let nextState = _.cloneDeep(state)
// 比较 prevState 和 nextState...
// 保存状态,用于下一次 mutation
prevState = nextState
})
}
日志上报
import {logAPI} from '@/api/logs';
export default function createLogsPlugins(store) {
store.subscribe((mutations, state) => {
logAPI(mutations.type, mutations.payload); // 上报接口
})
}
上面三种使用场景,前两种来源官方的 DEMO,后一种是小编项目中使用到情况,大家看情况使用吧。(~ ̄▽ ̄)~
至此,本篇文章就写完啦,撒花撒花。
希望本文对你有所帮助,如有任何疑问,期待你的留言哦。
老样子,点赞+评论=你会了,收藏=你精通了。