讲讲项目里的状态存储器vuex

前言

        在一个企业级的应用里,状态存储器起着举足轻重的作用。与我们日常的练手项目不同,企业级项目的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专门用来放置状态管理相关的逻辑

        讲讲项目里的状态存储器vuex_第1张图片

 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');

       缕清了最基本的引用思路,我们再回头来仔细琢磨里面的门道。

store/index.js

        这个文件是需要抛出一个vuex实例给vue用的。

export default new Vuex.Store({
    ...
})

        这里面仓库和方法等属性都是空的

new Vuex.Store({
  state: {},
  mutations: {},
  actions: {},
  strict: true,
  ...
}

        因为我们要借助模块化思想来书写这个状态管理器

讲讲项目里的状态存储器vuex_第2张图片

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,
    ...
  },
  ...
}

讲讲项目里的状态存储器vuex_第3张图片

        此时这个项目结构就很简单清晰啦 ,我们来看看模块的状态管理器长啥样

讲讲项目里的状态存储器vuex_第4张图片

        其实就是和状态管理器一样,有state有mutations ,甚至你喜欢的话,还可以往里面继续嵌套模块module。形成三级、四级、五级等等多层级的模块化状态管理器。

        细心的朋友,看到这里有个namespaced啦。如果不了解命名空间的相关知识,请看我这篇推文,否则后面可能会理解不了。

Vuex命名空间及如何获取根模块、兄弟模块状态管理器_AI3D_WebEngineer的博客-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/weixin_42274805/article/details/133269196?spm=1001.2014.3001.5502

优雅书写命名空间

       项目使用的是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}跟传参区分开来。注意传参如果有多个,最好用对象传参!

你可能感兴趣的:(三叠云项目,vue.js,javascript,前端)