Vuex

作者: 迷失的信徒 | 来源:发表于2022-04-19 17:54 被阅读0次

    一、Vuex是什么?

    官方解释为:Vuex是一个转为Vue.js应用程序开发的状态管理模式

    • 它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
    • Vuex也集成了Vue官方调试工具devtools extension,提供了诸如零配置的time-travel调试、状态快照导入导出等高级调试功能。

    通俗点来说,他就是个单例,任何一个用到单例中同一变量的地方,只要有一处修改了变量的值,其他的地方也会响应式的变化,最终保持一致。

    我们把需要共享的状态(变量)抽取出来,交给Vuex统一管理,然后我们按照规定好的规则,进行访问和修改等操作;这就是Vuex背后的基本思想。

    Backend API.png

    二、Vuex的引入和使用

    这里以webpack@3.6.0为例

    • npm install vuex@3.6.2 --save
    • 类似于vue-router在文件src下创建store文件夹,然后在其中创建index.js文件
    import Vue from "vue"
    import Vuex from 'vuex'
    
    //1、安装插件
    Vue.use(Vuex)
    //2、创建对象
    const store = new Vuex.Store({
      state:{
      },
      //修改state对象的话,至少要经过mutations中的方法
      mutations:{
      },
      //异步延时操作
      actions:{
      },
      getters:{//类似于计算属性
      },
      modules:{
      }
    })
    //3、导出store对象
    export default store
    
    • 然后在在main.js中使用即可
    import Vue from 'vue'
    import App from './App'
    import store from './store'
    Vue.config.productionTip = false
    
    /* eslint-disable no-new */
    new Vue({
      el: '#app',
      store,
      render: h => h(App)
    })
    

    注意:这里的store好像一定要取这个名,我试了一下其他的,好像拿不到值;很奇怪!!!

    三、Vuex核心概念

    1、State-单一状态树

    单一状态树:英文名称Single Source of Truth,也可以翻译成单一数据源。
    Vuex使用了单一状态树来管理应用层级的全部状态。
    单一状态树能够让以我们最直接的方式找到某个状态的片段,而且在之后的维护和调试过程中,也可以非常方便的管理和维护。

    state:{
        counter:200,
        students:[
          {id:100,name:'zhangsan',age:18},
          {id:101,name:'lisi',age:10},
          {id:102,name:'wangwu',age:23},
          {id:103,name:'zhaoliu',age:33}
        ]
      },
    

    这里以展示counter为例
    组件中使用为:$store.state.counter

    2、Getters

    可以把他的作用理解成计算属性。

    • 1、如我们需要展示counter的平方 ,我们在getters中添加一下方法;
    powerCounter(state){
          return state.counter * state.counter
        },
    

    并在相应的组件中使用:$store.getters.powerCounter

    • 2、展示年龄大于15岁的学生,getters中添加方法
    more15stu(state){
          return state.students.filter(s => s.age > 15)
        },
    

    组件中使用:$store.getters.more15stu

    • 3、getters作为参数,年龄大于15岁学生的个数
    more15stulength(state,getters){
          return getters.more15stu.length
        },
    

    使用:$store.getters.more15stulength

    • 4、传递参数,年龄为参数age,展示大于年龄age的学生信息
    moreagestu(state){//传参
          return age => {
            return state.students.filter(s => s.age > age)
          }
        }
    

    注意:传递参数时,返回一个带有入参的函数。

    使用:$store.getters.moreagestu(19)

    3、Mutations

    Vuex的store状态的状态更新唯一方式:提交mutations
    通常情况下,Vuex要求我们Mutations中方法必须是同步函数。

    • 主要原因是当我们使用devtools时,devtools可以帮助我们捕捉mutations的快照。
    • 但是如果是异步操作,那么devtools将不能很好的追踪这个操作什么时候被完成。
    3.1、基本用法

    如在App.vue组件中通过点击按钮来加减counter

    • 先在mutations定义以下两个方法
        increment(state){
          state.counter++
        },
        decrement(state){
          state.counter--
        }
    
    • 然后在组件中使用
    <template>
      <div id="app">
        <button @click="addition">+</button>
        <button @click="subraction">-</button>
      </div>
    </template>
    
    <script>
    export default {
      name: 'App',
      methods:{
        addition(){
          this.$store.commit('increment')
        },
        subraction(){
          this.$store.commit('decrement')
        }
      }
    }
    </script>
    
    <style>
    </style>
    

    通过事件来调用this.$store.commit('increment')

    3.2、带参

    参数被称为是mutations的载荷(payload)

    • 可以是一个数字
      mutations:{
        incrementCount(state,count){
          state.counter += count
        }
      },
    

    使用:

    addition(){
          this.$store.commit('incrementCount',10)
        },
    
    • 也可以是一个对象
      mutations:{
        addStudent(state,stu){
          state.students.push(stu)
        }
      },
    

    用法:

    addition(){//方法名可以随便哈,我这里只是懒的写了
          const stu = {id:144,name:'kk',age:49}
          this.$store.commit('addStudent',stu)
        },
    
    3.3、特殊提交风格

    提交

    this.$store.commit({
      type:'changeCount',
      count
    })
    

    将整个commit对象作为payload来使用

    changeCount(state,payload){
      state.count += payload.count
    }
    
    3.4、响应规则
    • 提前在store中初始化好所需属性的
      添加新属性方式:使用Vue.set(obj,'newProp',123)
      state:{
        info:{id:120,name:'kk',age:33}
      },
      //修改state对象的话,至少要经过mutations中的方法
      mutations:{
        addprops(state){//添加属性
          Vue.set(state.info,'address','开封')
        },
        delectprops(state){//删除属性
          Vue.delete(state.info,'age')
        }
      },
    
    3.5、mutations常量类型
    • 随着项目的越来越大,在mutations中我们定义方法也就越来越多。
    • 方法多了,我们往往会记不住,且还需要多个文件之间来回的切换,不复制的情况下还容易写错,所以这里引入了常量类型来管理

    在store文件目录下,创建mutations-type.js

    export const INCREMENT = 'increment'
    

    在index.js中引入、定义

    import {INCREMENT} from './mutations-types.js'
    [INCREMENT](state){
          state.counter++
        },
    

    在组件中使用

    import {INCREMENT} from './mutations-types.js'
    addition(){
          this.$store.commit(INCREMENT)
        },
    

    4、Action

    Action类似于Mutations,但是是用来替代Mutations进行异步操作的。
    一段时间后再做某项操作

      mutations: {
        [INCREMENT](state) {
          state.counter++
        },
      },
      //异步操作
      actions: {
        asyAdd(context) {
          setTimeout(() => {
            content.commit(INCREMENT)
          },1000)
        }
      },
    

    这里的context对应的就是store对象
    通过this.$store.dispatch('asyAdd')调用。

    带参:asyAdd(context,payload)his.$store.dispatch('asyAdd',abc)

    • 异步且有回调能知道什么时候有结果的
    asyAdd(context,payload) {
          return new Promise((resolve,reject) => {
            content.commit(INCREMENT)
            console.log(payload);
            resolve()
          })
        }
    
    this.$store.dispatch('asyAdd','我是携带的参数').then(res => {
            console.log('异步操作已完成');
            console.log(res);
          })
    

    5、Modules

    项目越大、store对象管理的状态也会越来越多,从而会变得很臃肿,module就是将store分割成不同的模块,有着自己的state、mutations、actions、getters.

    const moduleA = {
      state:{
        name:'abc'
      },
      mutations:{
        updataName(state,payload){
          state.name = payload
        }
      },
      actions:{
        aupNname(context){
          setTimeout(() => {
            context.commit('updataName','lisi')//
          },1000)
        }
      },
      getters:{
        fullname(state){
          return state.name + '1111'
        },
        fullname1(state,getters,rootState){
          return getters.fullname + rootState.counter
        }
      },
    }
    
    modules: {
        a:moduleA
      }
    
    • 通过$store.state.a.name获取a中state里面name的值。
    • 同样是通过this.$store.commit('updataName','lisi')来修改name的值
    • 同样是通过$store.getters.fullname来展示;但可以多了rootState参数。
    • actions还是以this.$store.dispatch('aupNname')调用;但是这里面的context和rootState里面actions里面的context是不一样的。

    相关文章

      网友评论

          本文标题:Vuex

          本文链接:https://www.haomeiwen.com/subject/lslsertx.html