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


    前言

            在一个企业级的应用里,状态存储器起着举足轻重的作用。与我们日常的练手项目不同,企业级项目的vuex更专注更集中更便捷。

    简单回顾

            让我们简单回顾一下vuex这个插件的用法。

       Vuex 的状态存储是响应式的。

             当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。

       只能通过mutation改变vuex里面的store。不能直接改变store里面的状态

    1. mutations: {
    2. setViewList(state, list) {
    3. state.viewList = list;
    4. }
    5. }

            集中化、显式化地修改stroe里的状态,方便管理方便阅读。

      最简单的例子

    1. import { createApp } from 'vue'
    2. import { createStore } from 'vuex'
    3. // 创建一个新的 store 实例
    4. const store = createStore({
    5. state () {
    6. return {
    7. count: 0
    8. }
    9. },
    10. mutations: {
    11. increment (state) {
    12. state.count++
    13. }
    14. }
    15. })
    16. const app = createApp({ /* 根组件 */ })
    17. // 将 store 实例作为插件安装
    18. app.use(store)

             vue组件里:

    1. methods: {
    2. update() {
    3. // 修改
    4. this.$store.commit('increment')
    5. // 查看
    6. console.log(this.$store.state.count)
    7. }
    8. }

    项目里的应用

            我们在项目的src文件夹里创建一个store专门用来放置状态管理相关的逻辑

            

     index.js:

    1. import Vue from 'vue';
    2. import Vuex from 'vuex';
    3. Vue.use(Vuex);

            index是整个状态管理的入口文件,Vue.use(Vuex)会在创建vue实例之前执行。Vue.use的作用想必大家都很清楚了:安装 Vue.js 插件,如果传入的是一个对象,则会执行它的install方法。如果传入的是一个函数,那么他将执行这个函数。

            举个例子:

    1. // plugin.js ————src\plugin\plugin.js
    2. export const plugin = {
    3. install() {
    4. alert("我是install内的代码")
    5. },
    6. }
    7. // main.js中引入自定义插件
    8. import Vue from "vue"
    9. import {Plugin} from './plugin/plugin.js'
    10. Vue.use(plugin) // 页面显示"我是install内的代码"

            当然啦,index.js会被Vue实例调用

    1. import store from './store';
    2. import router from './router';
    3. import App from './App.vue';
    4. // 初始化Vue
    5. new Vue({
    6. router,
    7. store,
    8. render: h => h(App),
    9. }).$mount('#app');

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

    store/index.js

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

    1. export default new Vuex.Store({
    2. ...
    3. })

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

    1. new Vuex.Store({
    2. state: {},
    3. mutations: {},
    4. actions: {},
    5. strict: true,
    6. ...
    7. }

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

    1. import global from './modules/global';
    2. import form from './modules/form';
    3. import formDesign from './modules/form-design';
    4. ...
    5. const store = new Vuex.Store({
    6. state: {},
    7. mutations: {},
    8. actions: {},
    9. strict: true,
    10. modules: {
    11. global,
    12. form,
    13. formDesign,
    14. ...
    15. },
    16. ...
    17. }

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

            其实就是和状态管理器一样,有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的方法:

    1. // store/index.js
    2. export default new Vuex.Store({
    3. state : {
    4. count : -1,
    5. },
    6. mutations: {
    7. addcount(state){
    8. state.count++
    9. }
    10. },
    11. actions: {
    12. change({commit}){
    13. commit("addcount")
    14. }
    15. },
    16. })
    1. // page.vue
    2. //首先引入
    3. import {Action,State} from'vuex-class'
    4. //直接使用装饰器就可以获取到了
    5. @State('count') globalCount
    6. @Action('change') changecount
    7. //然后就是直接调用
    8. create(){
    9. log(`vuex中的count数据为${this.globalCount}`)
    10. }
    11. add(){
    12. //调用一次add()就触发一次
    13. this.changecount()
    14. }

            这样子确实能用,但不美观。我们结合命名空间来优雅地书写 。

            3.分模块使用

            当分模块调用state、mutations、actions、getters时,需要引入namespace,并且调用的时候需要加上@nameSpaceName

            先来看日常是怎么写的:

    1. import common from './common'
    2. export default new Vuex.Store({
    3. state:{},
    4. modules: {
    5. // here here!
    6. common
    7. }
    8. })
    1. // common.js
    2. export default {
    3. namespaced: true,
    4. state: {count:0}
    5. mutations: {
    6. ADD_COUNT(state){
    7. state.count++
    8. }
    9. }
    10. }
    1. import {Action, namespace,State} from'vuex-class'
    2. // 获取com模块
    3. const mymodule = namespace('common')
    4. @Component()
    5. export default class HomeView extends Vue {
    6. @mymodule.State('count') stateCount
    7. @mymodule.Mutation('ADD_COUNT') addCount
    8. created() {
    9. console.log(this.stateCount)
    10. this.addCount()
    11. }
    12. }

            在项目里这么写肯定是没问题的,但是太繁琐,不工整。我们回归到项目里:

            src/store/index.js

    1. import Vue from 'vue';
    2. import Vuex from 'vuex';
    3. import global from './modules/global';
    4. import form from './modules/form';
    5. import formDesign from './modules/form-design';
    6. import application from './modules/application';
    7. import formSetting from './modules/form-setting';
    8. import formPermission from './modules/form-permission';
    9. import formView from './modules/form-view';
    10. import file from './modules/file';
    11. ...
    12. Vue.use(Vuex);
    13. const store = new Vuex.Store({
    14. state: {},
    15. mutations: {},
    16. actions: {},
    17. strict: true,
    18. modules: {
    19. global,
    20. form,
    21. formDesign,
    22. application,
    23. formSetting,
    24. file,
    25. ...
    26. }
    27. });
    28. export default store;

            紧接着,我们创建一个枚举类文件

            src/enum/store.js

    1. import { namespace } from 'vuex-class';
    2. export const globalModule = namespace('global');
    3. export const formModule = namespace('form');
    4. export const crossStorageModule = namespace('crossStorage');
    5. export const formDesignModule = namespace('formDesign');
    6. export const formSettingModule = namespace('formSetting');
    7. export const applicationModule = namespace('application');
    8. export const formPermissionModule = namespace('formPermission');
    9. export const formViewModule = namespace('formView');
    10. ...

            这么写有什么好处?其实就是把所有的命名空间模块枚举出来。实现按需引入。

            具体项目文件:不需要再引入import {Action, namespace,State} from'vuex-class'

    1. import { formDesignModule, applicationModule } from '@/enum/store';
    2. ...
    3. @Component({
    4. components: {},
    5. })
    6. export default class DashboardDesignLayout extends Vue {
    7. ...
    8. @formDesignModule.State form;
    9. @formDesignModule.Action init;
    10. @formDesignModule.Mutation reset;
    11. @applicationModule.Action getApplicationDetail;
    12. @applicationModule.State applicationDetail;
    13. @formDesignModule.Mutation saveForm;
    14. @formDesignModule.Getter isFormStatistics;
    15. @formDesignModule.Getter isApplicationHome;
    16. }

             注意一下。比如我们要用这个init方法。项目里应该这么写:

    1. async handleEdit() {
    2. ....
    3. await this.init(result.pkId);
    4. }

            vuex里应该这么写:

    1. actions: {
    2. async init({ commit }, formId) {
    3. const form = await getFormData(formId);
    4. commit('saveForm', form);
    5. },
    6. }

            用{commit, state,getters,dispatch}跟传参区分开来。注意传参如果有多个,最好用对象传参!

  • 相关阅读:
    396. 旋转函数
    Chrome 118 版本中的新功能
    半导体应用系统一些小知识收集(strip&wafer mapping,EAP&scada)
    nodejs+vue+elementui在线音乐分享网站管理系统
    2.21 haas506 2.0开发教程 - TTS - Text To Speech (320开发板)
    李航统计学习方法python实现-决策树2-sklearn
    JavaFX中Application、Stage、Scene和Parent的区别
    【java基础系列】16- Java中怎么处理异常?
    算法之排序
    Java远程操作Linux服务器命令
  • 原文地址:https://blog.csdn.net/weixin_42274805/article/details/133237271