在一个企业级的应用里,状态存储器起着举足轻重的作用。与我们日常的练手项目不同,企业级项目的vuex更专注更集中更便捷。
让我们简单回顾一下vuex这个插件的用法。
Vuex 的状态存储是响应式的。
当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
只能通过mutation改变vuex里面的store。不能直接改变store里面的状态
- mutations: {
- setViewList(state, list) {
- state.viewList = list;
- }
- }
集中化、显式化地修改stroe里的状态,方便管理方便阅读。
最简单的例子
- import { createApp } from 'vue'
- import { createStore } from 'vuex'
-
- // 创建一个新的 store 实例
- const store = createStore({
- state () {
- return {
- count: 0
- }
- },
- mutations: {
- increment (state) {
- state.count++
- }
- }
- })
-
- const app = createApp({ /* 根组件 */ })
-
- // 将 store 实例作为插件安装
- app.use(store)
vue组件里:
- methods: {
- update() {
- // 修改
- this.$store.commit('increment')
- // 查看
- console.log(this.$store.state.count)
- }
- }
我们在项目的src文件夹里创建一个store专门用来放置状态管理相关的逻辑
index.js:
- import Vue from 'vue';
- import Vuex from 'vuex';
-
- Vue.use(Vuex);
index是整个状态管理的入口文件,Vue.use(Vuex)会在创建vue实例之前执行。Vue.use的作用想必大家都很清楚了:安装 Vue.js 插件,如果传入的是一个对象,则会执行它的install方法。如果传入的是一个函数,那么他将执行这个函数。
举个例子:
- // plugin.js ————src\plugin\plugin.js
- export const plugin = {
- install() {
- alert("我是install内的代码")
- },
- }
-
- // main.js中引入自定义插件
- import Vue from "vue"
- import {Plugin} from './plugin/plugin.js'
- Vue.use(plugin) // 页面显示"我是install内的代码"
当然啦,index.js会被Vue实例调用
- import store from './store';
- import router from './router';
- import App from './App.vue';
-
- // 初始化Vue
- new Vue({
- router,
- store,
- render: h => h(App),
- }).$mount('#app');
缕清了最基本的引用思路,我们再回头来仔细琢磨里面的门道。
这个文件是需要抛出一个vuex实例给vue用的。
- export default new Vuex.Store({
- ...
- })
这里面仓库和方法等属性都是空的
- new Vuex.Store({
- state: {},
- mutations: {},
- actions: {},
- strict: true,
- ...
- }
因为我们要借助模块化思想来书写这个状态管理器
- import global from './modules/global';
- import form from './modules/form';
- import formDesign from './modules/form-design';
- ...
-
- const store = new Vuex.Store({
- state: {},
- mutations: {},
- actions: {},
- strict: true,
- modules: {
- global,
- form,
- formDesign,
- ...
- },
- ...
- }
此时这个项目结构就很简单清晰啦 ,我们来看看模块的状态管理器长啥样
其实就是和状态管理器一样,有state有mutations ,甚至你喜欢的话,还可以往里面继续嵌套模块module。形成三级、四级、五级等等多层级的模块化状态管理器。
细心的朋友,看到这里有个namespaced啦。如果不了解命名空间的相关知识,请看我这篇推文,否则后面可能会理解不了。
项目使用的是ts+vue。所以借助Vuex-class进行绑定(主要用于Vue2.0+TS使用store的全局变量和方法)
使用方法:
1.安装vuex-class
npm install --save vuex-class
2.全局使用vuex-class的方法:
- // store/index.js
- export default new Vuex.Store({
- state : {
- count : -1,
- },
-
- mutations: {
- addcount(state){
- state.count++
- }
- },
-
- actions: {
- change({commit}){
- commit("addcount")
- }
- },
- })
- // page.vue
-
- //首先引入
-
- import {Action,State} from'vuex-class'
-
- //直接使用装饰器就可以获取到了
- @State('count') globalCount
- @Action('change') changecount
-
- //然后就是直接调用
- create(){
- log(`vuex中的count数据为${this.globalCount}`)
- }
- add(){
- //调用一次add()就触发一次
- this.changecount()
- }
这样子确实能用,但不美观。我们结合命名空间来优雅地书写 。
3.分模块使用
当分模块调用state、mutations、actions、getters时,需要引入namespace,并且调用的时候需要加上@nameSpaceName
先来看日常是怎么写的:
- import common from './common'
- export default new Vuex.Store({
- state:{},
- modules: {
- // here here!
- common
- }
- })
- // common.js
- export default {
- namespaced: true,
- state: {count:0}
- mutations: {
- ADD_COUNT(state){
- state.count++
- }
- }
- }
- import {Action, namespace,State} from'vuex-class'
-
- // 获取com模块
- const mymodule = namespace('common')
-
-
-
- @Component()
- export default class HomeView extends Vue {
- @mymodule.State('count') stateCount
- @mymodule.Mutation('ADD_COUNT') addCount
-
- created() {
- console.log(this.stateCount)
- this.addCount()
- }
-
- }
在项目里这么写肯定是没问题的,但是太繁琐,不工整。我们回归到项目里:
src/store/index.js
- import Vue from 'vue';
- import Vuex from 'vuex';
- import global from './modules/global';
- import form from './modules/form';
- import formDesign from './modules/form-design';
- import application from './modules/application';
- import formSetting from './modules/form-setting';
- import formPermission from './modules/form-permission';
- import formView from './modules/form-view';
- import file from './modules/file';
- ...
-
-
- Vue.use(Vuex);
-
- const store = new Vuex.Store({
- state: {},
- mutations: {},
- actions: {},
- strict: true,
- modules: {
- global,
- form,
- formDesign,
- application,
- formSetting,
- file,
- ...
- }
- });
-
- export default store;
紧接着,我们创建一个枚举类文件
src/enum/store.js
- import { namespace } from 'vuex-class';
-
- export const globalModule = namespace('global');
- export const formModule = namespace('form');
- export const crossStorageModule = namespace('crossStorage');
- export const formDesignModule = namespace('formDesign');
- export const formSettingModule = namespace('formSetting');
- export const applicationModule = namespace('application');
- export const formPermissionModule = namespace('formPermission');
- export const formViewModule = namespace('formView');
- ...
这么写有什么好处?其实就是把所有的命名空间模块枚举出来。实现按需引入。
具体项目文件:不需要再引入import {Action, namespace,State} from'vuex-class'
- import { formDesignModule, applicationModule } from '@/enum/store';
- ...
-
- @Component({
- components: {},
- })
- export default class DashboardDesignLayout extends Vue {
- ...
- @formDesignModule.State form;
- @formDesignModule.Action init;
- @formDesignModule.Mutation reset;
- @applicationModule.Action getApplicationDetail;
- @applicationModule.State applicationDetail;
- @formDesignModule.Mutation saveForm;
- @formDesignModule.Getter isFormStatistics;
- @formDesignModule.Getter isApplicationHome;
- }
注意一下。比如我们要用这个init方法。项目里应该这么写:
- async handleEdit() {
- ....
- await this.init(result.pkId);
- }
vuex里应该这么写:
- actions: {
- async init({ commit }, formId) {
- const form = await getFormData(formId);
- commit('saveForm', form);
- },
- }
用{commit, state,getters,dispatch}跟传参区分开来。注意传参如果有多个,最好用对象传参!