> 文章列表 > 20230422----重返学习-vue数据集中管理vuex

20230422----重返学习-vue数据集中管理vuex

20230422----重返学习-vue数据集中管理vuex

day-055-fifty-five-20230422-vue数据集中管理vuex

vuex

vuex的说明

  • vuex是专门为vue提供的大仓库,采用状态管理的大仓库
  • Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
    • 它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

vuex与vue版本的关联

  • 一般vuex要比vue的版本多1
    • vue2 —> vuex3
    • vue3 —> vuex4

vuedevtools安装

  1. 解压vuedevtools文件夹
  2. 打开谷歌浏览器进行安装
    • 网页右上角没有的V可以点开这个拼图图标,然后把V置顶就出现了
  3. 安装完成后,需要重新启动vue项目

安装vuex

  • 方法1. 创建项目的时候,直接选vuex

    1. src目录先多一个文件夹 store —> index.js(写好的模板)导出仓库
      • 多一个文件/src/store/index.js,里面会让vue使用vuex这个插件,同时初始化一个Vuex实例对象,并导出。

        import Vue from 'vue'
        import Vuex from 'vuex'
        Vue.use(Vuex)//让Vue构造函数使用了Vuex这个vue插件
        const store=new Vuex.Store({})// 创建一个Vuex实例对象
        export default store;// 导出Vuex实例对象
        
      • /src/main.js中会导入Vuex实例对象,并将其挂载到根Vue实例对象上。

        import store from './store'
        let vm=new Vue({store,render: h => h(App)
        }).$mount('#app')
        
  • 方法2. 创建项目的,没有选择vuex

    1. 重新安装vuex这个vue插件的npm依赖

      npm install vuex --save//使用npm方式,个人推荐,最基础的方式
      //yarn add vuex//yarn方式,npm方式因网络不好时再用
      
    2. 安装好vuex之后,项目中关于vuex的什么基础操作都没有,需要自己手动编写和操作

      • 安装依赖的作用,主要是可以通过import Vuex from 'vuex'在项目中可以导入Vuex这个vue插件。
    3. src目录先多一个文件夹 store —> index.js(写好的模板)导出仓库

      • 多一个文件/src/store/index.js,里面会让vue使用vuex这个插件,同时初始化一个Vuex实例对象,并导出。

        import Vue from 'vue'
        import Vuex from 'vuex'
        Vue.use(Vuex)//让Vue构造函数使用了Vuex这个vue插件
        const store=new Vuex.Store({})// 创建一个Vuex实例对象
        export default store;// 导出Vuex实例对象
        
      • /src/main.js中会导入Vuex实例对象,并将其挂载到根Vue实例对象上。

        import store from './store'
        let vm=new Vue({store,render: h => h(App)
        }).$mount('#app')
        

vue五大模块

  • state: {} 相当于vue中的data

    • 设置值:

      export default new Vuex.Store({state: {num:100,str:"hello"}
      })
      
    • 获取值:

      • 通过this.$store.state拿到state对象里的数据

        1. 直接取

          <template><div>{{ $store.state.num }}</div>
          </template>
          
          <script>
          export default {mounted() {this.$store.state.num}
          };
          </script>
          
        2. 通过data取

          <script>
          export default {data(){return {dataNum:this.$store.state.num}}
          };
          </script>
          
        3. 通过computed

          • 推荐
          <script>
          export default {computed:{//推荐dataNum(){return this.$store.state.num}}
          };
          </script>
          
      • 通过mapState()辅助函数拿到state对象里的数据

        1. mapState()辅助函数

          • 推荐
          <template><div>{{ num }}--{{ str }}</div>
          </template>
          <script>
          import { mapState } from 'vuex';
          export default {computed:mapState(["num","str"])
          };
          </script>
          
          • 步骤

            1. 引入

              import { mapState } from 'vuex';
              
            2. 配合计算属性使用

              computed:mapState(["num","str"])
              
              computed:{...mapState(["num","str"])}
              
          • 使用类型

            • 数组:直接接收,直接使用

              <template><div>{{ num }}--{{ str }}</div>
              </template>
              <script>
              import { mapState } from 'vuex';
              export default {computed:mapState(["num","str"])
              };
              </script>
              
            • 对象:接收后,换一个名称

              <template><div>{{ nn }}---{{ ss }}---{{ mm }}</div>
              </template>
              <script>
              import { mapState } from 'vuex';
              export default {computed:mapState({nn:state=>state.num,//使用函数的方式ss:"str",//使用字符串的方式//使用函数ES6简写的方式mm(state){return state.num+200}})
              };
              </script>
              
          • 辅助函数 与 计算属性的其他属性共存

            <template><div>{{ nn }}---{{ fullName }}---{{ str }}</div>
            </template>
            <script>
            import { mapState } from 'vuex';
            export default {computed:{...mapState({nn:state=>state.num}),fullName(){return 5555},...mapState(['str'])}
            };
            </script>
            
  • getters: {}: 相当于vue中的计算属性,对state的数据二次处理

    • 函数的写法,属性的用法。

    • 设置值:

      export default new Vuex.Store({state: {arr:[10,20,30,40,50,60]},getters:{//函数的写法,属性的用法//作用 state里面的数据进行二次处理返回//箭头函数写法newarr:(state)=>{return state.arr.filter((item)=>item>30)}//ES6写法//newarr(state) {//  return state.arr.filter((item) => item > 30);//},}
      })
      
      export default new Vuex.Store({state: {arr:[10,20,30,40,50,60]},getters:{//ES6写法newarr(state) {return state.arr.filter((item) => item > 30);},}
      })
      
    • 获取值:

      • 通过this.$store.state拿到getters对象里的数据

        1. 直接取

          <template><div>{{ $store.getters.newarr }}</div>
          </template>
          
          <script>
          export default {mounted() {this.$store.getters.newarr}
          };
          </script>
          
        2. 通过data取

          <script>
          export default {mounted() {this.dataNum},data(){return {dataNum:this.$store.getters.newarr}}
          };
          </script>
          
        3. 通过computed

          • 推荐
          <script>
          export default {mounted() {this.computedNum},computed:{//推荐computedNum(){return this.$store.getters.newarr}}
          };
          </script>
          
      • 通过mapGetters()辅助函数拿到getters对象里的数据

        1. mapGetters()辅助函数

          • 推荐
          <template><div>{{ newarr }}</div>
          </template>
          <script>
          import { mapGetters } from 'vuex';
          export default {computed:mapGetters(["newarr"])
          };
          </script>
          
          • 步骤

            1. 引入

              import { mapGetters } from 'vuex';
              
            2. 配合计算属性使用

              computed:mapGetters(["newarr"])
              
              computed:{...mapGetters(["newarr"])}
              
          • 使用类型

            • 数组:直接接收,直接使用

              <template><div>{{ newarr }}</div>
              </template>
              <script>
              import { mapGetters } from 'vuex';
              export default {computed:mapGetters(["newarr"])
              };
              </script>
              
            • 对象:接收后,换一个名称

              <template><div>{{ arr }}</div>
              </template>
              <script>
              import { mapGetters } from 'vuex';
              export default {computed:mapGetters({arr:"newarr"})
              };
              </script>
              
          • 辅助函数 与 计算属性的其他属性共存

            <template><div>{{ newarr }}---{{ arr }}</div>
            </template>
            <script>
            import { mapGetters } from 'vuex';
            export default {computed:{...mapGetters(["newarr"]),fullName(){return 5555},...mapGetters({arr:"newarr"})}
            };
            </script>
            
  • mutations: {} 同步方法(仓库管理员)

    • vuex是单向数据流,state只能通过Mutation来修改

    • 设置方法:

      export default new Vuex.Store({state: {num:100},mutations: {//箭头函数写法//无入参addNum:(state)=>{state.num++},}
      })
      
      export default new Vuex.Store({state: {num:100},mutations: {//箭头函数写法//有入参addNum:(state,payload)=>{//console.log(payload);//state.num++state.num+=payload.n;}}
      })
      
      export default new Vuex.Store({state: {num:100},mutations: {//ES6简写写法//无入参addNum(state){state.num++},}
      })
      
      export default new Vuex.Store({state: {num:100},mutations: {//ES6简写写法//有入参addNum(state,payload){console.log(payload);state.num+=payload.n;}}
      })
      
    • 使用方法:

      • 通过this.$store.commit()使用mutations对象里的同步方法

        • 要想执行 mutations里面的方法,必须通过 commit()

          • commit(函数名,参数) 只有两个值
            • 如果第二个参数那里,想要传递多个内容,可以使用数组,对象
          <template><div>{{ $store.state.num }}<button @click="add">add</button></div>
          </template><script>
          export default {methods:{//  add(){//页面数据可以修改,仓库数据无法修改//     this.$store.state.num++;//  }add(){//要想执行 mutations里面的方法,必须通过 commit()//commit(函数名,参数) 只有两个值  //如果第二个“参数”,想要传递多个内容,数组,对象this.$store.commit("addNum",{n:10,m:20})}}
          }
          </script>
          
      • 通过mapMutations()辅助函数使用mutations对象里的同步方法

        1. mapMutations()辅助函数

          <template><div>{{ $store.state.num }}<button @click="add({n:10,m:20})">add</button></div>
          </template>
          <script>
          import { mapMutations } from 'vuex';
          export default {methods:{...mapMutations({add:"addNum"})}
          };
          </script>
          
          • 步骤

            1. 引入

              import { mapMutations } from 'vuex';
              
            2. 配合methods属性使用

              methods:mapMutations({add:"addNum"})
              
              methods:{...mapMutations({add:"addNum"})}
              
          • 使用类型

            • 数组:直接接收,直接使用

              <template><div>{{ $store.state.num }}<button @click="addNum({n:10,m:20})">addNum</button></div>
              </template>
              <script>
              import { mapMutations } from 'vuex';
              export default {methods:mapMutations(["addNum"]),
              };
              </script>
              
            • 对象:接收后,换一个名称

              <template><div>{{ $store.state.num }}<button @click="add({n:10,m:20})">add</button></div>
              </template>
              <script>
              import { mapMutations } from 'vuex';
              export default {methods:mapMutations({add:"addNum"}),
              };
              </script>
              
          • 辅助函数 与 methods的其他方法共存

            <template><div>{{ $store.state.num }}<button @click="addNum({n:10,m:20})">addNum</button><button @click="add({n:10,m:20})">add</button></div>
            </template>
            <script>
            import { mapMutations } from 'vuex';
            export default {methods:{...mapMutations(["addNum"]),...mapMutations({add:"addNum"})}
            };
            </script>
            
  • actions: {}

    • 设置异步方法

      export default new Vuex.Store({state: {n:10}mutations: {addN(state,payload){//通过mutations做异步操作效果实现的不对state.n+=payload;}},actions: {AsyncAddN(context,payload){//console.log(context);//{commit,...}setTimeout(() => {context.commit("addN",payload);}, 1000);}}
      })
      
    • 使用异步方法

      <template><div>{{ $store.state.n }}<button @click="addN()">addN</button></div>
      </template><script>
      export default {methods:{addN(){//this.$store.commit("addN")//通过dispatch来调用 actionsthis.$store.dispatch("AsyncAddN",10)}}
      }
      </script>
      
    • 使用辅助函数-对象可改名

      <template><div>{{ $store.state.n }}<button @click="add(10)">add</button></div>
      </template><script>
      import { mapActions } from 'vuex';
      export default {methods:{...mapActions({add:"AsyncAddN"})}
      }
      </script>
      
    • 使用辅助函数-数组不可改名

      <template><div>{{ $store.state.n }}<button @click="AsyncAddN(10)">add</button></div>
      </template><script>
      import { mapActions } from 'vuex';
      export default {methods:{...mapActions(["AsyncAddN"])}
      }
      </script>
      
  • modules: {} 模块,将仓库进行划分,每个模块仍然具有五部分

    • 模式一: 不区别getters与mutations等

      • 设置

        const ModelA={state:{arra:[1,2,3,4,5]},getters:{newarra(store){return store.arra.filter((item)=>{return item>3})}}
        }const ModelB={state:{numb:200},mutations:{changeNum(state){state.numb+=10;}}
        }export default new Vuex.Store({modules: {a:ModelA,b:ModelB}
        })
        
      • 使用

        <template><div>{{ $store.state.b.numb }}{{ $store.getters.newarra }}<button @click="changeNum()">changeNum</button></div>
        </template><script>
        import { mapMutations } from 'vuex';
        export default {methods:{...mapMutations(["changeNum"])}
        }
        </script>
        
    • 模式二:使用命名空间,区别getters与mutations等

      namespaced: true,//添加命名空间
      
      • 设置

        const ModelC = {namespaced: true,state: {arra: [1, 2, 3, 4, 5],},getters: {newarra(state) {return state.arra.filter((item) => item > 3);},},
        };const ModelD = {namespaced: true,state: {numd: 5,},mutations: {changeNumd(state, payload = 10) {state.numd += payload;},},actions: {asyncChangeNumd(context, payload = 100) {setTimeout(() => {context.commit("changeNumd", payload);}, 1000);},},
        };export default new Vuex.Store({modules: {c: ModelC,d: ModelD,}
        })
        
      • 使用

        • 方法一,使用命名空间直接访问

          <template><div><h1>ModulesView01</h1><div>$store.getters["c/newarra"] --- {{ $store.getters["c/newarra"] }}</div><div>mapGetters('c',['newarra']) --- {{ newarra }}</div><div>{{ $store.state.d.numd }}</div><div><button @click="changeNumd()">同步改变值-辅助函数-数组-mapMutations("d", ["changeNumd"])</button><button @click="asyncChangeNumd()">异步改变值-辅助函数-数组-mapActions("d", ["asyncChangeNumd"])</button></div><div><button @click="handleChange01()">同步改变值-commit-对象-mapMutations({ handleChange01: "d/changeNumd" })</button><button @click="handleChange02()">异步改变值-dispatch-对象-mapActions({ handleChange02:"d/asyncChangeNumd" })</button></div><div><button @click="handleChange03()">同步改变值-辅助函数-对象-mapMutations("d", { handleChange03:"changeNumd" })</button><button @click="handleChange04()">异步改变值-辅助函数-对象-mapActions("d", { handleChange04:"asyncChangeNumd" })</button></div><div><button @click="handleChange05()">同步改变值-commit-this.$store.commit("d/changeNumd", num)</button><button @click="handleChange06()">异步改变值-dispatch-this.$store.dispatch("d/asyncChangeNumd", num)</button></div></div>
          </template><script>
          import { mapGetters } from "vuex";
          import { mapMutations } from "vuex";
          import { mapActions } from "vuex";
          export default {computed: {...mapGetters("c", ["newarra"]),},methods: {...mapMutations("d", ["changeNumd"]), //常用,推荐使用方式...mapActions("d", ["asyncChangeNumd"]), //常用,推荐使用方式...mapMutations({ handleChange01: "d/changeNumd" }),...mapActions({ handleChange02: "d/asyncChangeNumd" }),...mapMutations("d", { handleChange03: "changeNumd" }),...mapActions("d", { handleChange04: "asyncChangeNumd" }),handleChange05() {this.$store.commit("d/changeNumd"); //常用,推荐使用方式},handleChange06() {this.$store.dispatch("d/asyncChangeNumd"); //常用,推荐使用方式},},
          };
          </script>
          
          • 简洁

            <template><div><h1>ModulesView01</h1><div>$store.getters["c/newarra"] --- {{ $store.getters["c/newarra"] }}</div><div>mapGetters('c',['newarra']) --- {{ newarra }}</div><div>{{ $store.state.d.numd }}</div><div><button @click="changeNumd()">同步改变值-辅助函数-数组-mapMutations("d", ["changeNumd"])</button></div></div>
            </template><script>
            import { mapGetters } from "vuex";
            import { mapMutations } from "vuex";
            export default {computed: {...mapGetters("c", ["newarra"]),},methods: {...mapMutations("d", ["changeNumd"]), //常用,推荐使用方式},
            };
            </script>
            
        • 方法二:使用import { createNamespacedHelpers } from "vuex";

          <template><div><h1>ModulesView01</h1><div>$store.getters["c/newarra"] --- {{ $store.getters["c/newarra"] }}</div><div>mapGetters(['newarra']) --- {{ newarra }}</div><div>{{ $store.state.d.numd }}</div><div><button @click="changeNumd()">同步改变值-辅助函数-数组-mapMutations(["changeNumd"])</button><button @click="asyncChangeNumd()">异步改变值-辅助函数-数组-mapActions(["asyncChangeNumd"])</button></div><div><button @click="handleChange01()">同步改变值-commit-对象-mapMutations({ handleChange01: "changeNumd" })</button><button @click="handleChange02()">异步改变值-dispatch-对象-mapActions({ handleChange02:"asyncChangeNumd" })</button></div><div><button @click="handleChange05()">同步改变值-commit-this.$store.commit("d/changeNumd", num)</button><button @click="handleChange06()">异步改变值-dispatch-this.$store.dispatch("d/asyncChangeNumd", num)</button></div></div>
          </template><script>
          import { createNamespacedHelpers } from "vuex";
          const { mapGetters } = createNamespacedHelpers("c");
          const { mapMutations } = createNamespacedHelpers("d");
          const { mapActions } = createNamespacedHelpers("d");
          export default {computed: {...mapGetters(["newarra"]),},methods: {...mapMutations(["changeNumd"]),...mapActions(["asyncChangeNumd"]),...mapMutations({ handleChange01: "changeNumd" }),...mapActions({ handleChange02: "asyncChangeNumd" }),handleChange05() {this.$store.commit("d/changeNumd"); //常用,推荐使用方式},handleChange06() {this.$store.dispatch("d/asyncChangeNumd"); //常用,推荐使用方式},},
          };
          </script>
          
          • 简洁

            <template><div><h1>ModulesView01</h1><div>$store.getters["c/newarra"] --- {{ $store.getters["c/newarra"] }}</div><div>mapGetters(['newarra']) --- {{ newarra }}</div><div>{{ $store.state.d.numd }}</div><div><button @click="changeNumd()">同步改变值-辅助函数-数组-mapMutations(["changeNumd"])</button></div><div><button @click="handleChange05()">同步改变值-commit-this.$store.commit("d/changeNumd", num)</button></div></div>
            </template><script>
            import { createNamespacedHelpers } from "vuex";
            const { mapGetters } = createNamespacedHelpers("c");
            const { mapMutations } = createNamespacedHelpers("d");
            export default {computed: {...mapGetters(["newarra"]),},methods: {...mapMutations(["changeNumd"]),handleChange05() {this.$store.commit("d/changeNumd"); //常用,推荐使用方式},},
            };
            </script>
            

vuex插件

  1. 日志插件

    • vuex自带一个日志插件用于一般的调试

      import createLogger from 'vuex/dist/logger'
      const store = new Vuex.Store({plugins: [createLogger()]
      })
      
  2. vuex数据持久化插件

    • 详见:vuex的数据持久化插件vuex-persistedstate

辅助函数

  • vuex有五大重要特性,有四个都有对应的辅助函数

    • 所有的辅助函数大多是一样的使用方式
  • State 相当于vue中的data

    • 辅助函数为mapState()

      import { mapState } from "vuex";
      
  • Getter 相当于vue中的计算属性,对State的数据二次处理

    • 辅助函数为mapGetters()

      import { mapGetters } from "vuex";
      
  • Mutation 管理同步方法,专门用来直接修改State中的数据的

    • 辅助函数为mapMutations()

      import { mapMutations } from "vuex";
      
  • Action 管理异步方法,专门用来调用的Mutation中的同步方法的

    • 辅助函数为mapActions()

      import { mapActions } from "vuex";
      
  • Module 管理模块的

vuex的作用

  • vuex一般有两个作用
    • 作用一: 实现数据通信
    • 作用二: 数据缓存 切换页面(前进后退),数据不变(缓存); 除非刷新或者关闭

配置一个路由

  1. 在/src/views/新建一个vue文件,例如叫MutationView.vue

    <template><div><h1>MutationView</h1></div>
    </template><script>
    export default {}
    </script>
    
  2. 在/src/router/index.js上进行修改,新添加一个动态路由

      //一个动态路由{path: '/mutationView',//这个是页面URL路径name: 'MutationView',//这个是路由页面名称component: () => import('../views/MutationView.vue')//这个路径是之前新建文件的文件名。}
    
    import Vue from 'vue'
    import VueRouter from 'vue-router'
    import HomeView from '../views/HomeView.vue'Vue.use(VueRouter)const routes = [{path: '/',name: 'home',component: HomeView},{path: '/about',name: 'about',component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')},{path: '/mutationView',//这个是页面URL路径name: 'MutationView',//这个是路由页面名称,也是webpack的chunk名称component: () => import('../views/MutationView.vue')//这个路径是之前新建文件的文件名。}
    ]const router = new VueRouter({routes
    })export default router
    
  3. 在根组件上,写一个router-link标签,用于跳转到新建的路由页面。

    • router-link标签的to属性与新建路由的页面URL路径保持一致
    <template><div id="app"><router-link to="/mutationView">MutationView</router-link><router-view/></div>
    </template>
    

进阶参考

  1. Vue2配合使用的Vuex3官方中文文档
  2. Vue3配合使用的Vuex4官方中文文档
  3. Vuex官方中文文档–一般照着这个来就行了-这个一般都是最新版最主流的
  4. vuedevtools-官方git仓库
  5. vuex内置-logger-插件
  6. vuex数据持久化插件