Vuex 状态管理

一、为什么使用vuex : https://www.cnblogs.com/goloving/p/9080005.html

  vuex的功能 和 localstorage 的作用是一样,把数据在一个所有页面都可以存取的地方。但是vuex的数据具有响应式(类似数据双向绑定),而 localstorage 的数据是固定的,必须手动设置。

  • 使用场景【不同组件中】:祖孙组件件的数据传递
  • Vuex 的缺点:vuex是存储在内存中的,刷新页面 或 跳转到 项目外的页面就会清除页面内存的数据,导致页面不能正常显示。【
                      app虽然没有刷新功能,但是跳到外联,在回退到页面。也是相当于刷新了页面。
    注意:跳出当前的单页应用,即不同html文件。再次返回时,也是相当于刷新了页面。
  • 解决Vuex的这个缺点:这个问题,只要设置Vuex值时,保存到localstorage 中。在刷新页面后 从localstorage 取出,再次 赋值进去就可以了。
    Vuex数据丢失的解决方案【刷新,跳转外链再返回】:https://blog.csdn.net/liuliuliu_666/article/details/93862880

二、vuex 的使用:

    https://www.cnblogs.com/hermit-gyqy/p/11270315.html(更直观) 或 https://blog.51cto.com/9161018/2351075(说明更详细)   或  https://vuex.vuejs.org/zh/guide/(官网)

  • state:存储状态(可以理解为变量)可以从计算属性中返回某个状态
  • getters:通常用在数据的二次处理(过滤数据...),可以理解为state的计算属性
    注意:如果需要根据传入的参数,获取对应对应的getters数据,可以通过返回一个函数实现。
      getters: { // 通常用在数据的二次处理(过滤数据...),可以理解为state的计算属性
        moreAgeStu(state) {
          return function(age) {
             return state.number + age
          } 
        }
      },
  • mutations:修改状态,并且是同步的。
    注意:有两种提交发生:
    • 普通提交风格:
      mutations: {
        increment (state, n) {
          state.count += n
        }
      }
      
      // 对应的提交方式 如下
      store.commit('increment', 10)
    • 特殊提交风格:载荷 Payload 风格
      mutations: {
        increment (state, payload) {
          state.count += payload.amount
        }
      }
      
      // 对应的提交方式如下
      store.commit('increment', {
        amount: 10
      })
      //
      store.commit({
        type: 'increment',
        amount: 10
      })
  • actions:异步操作。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

const store = new Vuex.Store({
  state: { // 存储状态(可以理解为变量)可以从计算属性中返回某个状态
    count: 8
  },
  getters: { // 通常用在数据的二次处理(过滤数据...),可以理解为state的计算属性
    newCount (state) {
      return state.count + 1    // 这里一旦count改变,newCount也会同步改变
    }
  },
  mutations: { // 修改状态,并且是同步的
    changeCount (state, val) {
      state.count = val
    }
  },
  actions: { // 异步操作
    actCount (context, val) {
      setTimeout(function () {
        context.commit('changeCount', val) // 利用es6解构赋值,可以直接可以获取到commit方法,不用是context.commit
      }, 1000)
    }
  }
})

export default store

  注:不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。

  • modules:模块化管理
    Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter 用法其实和上面是一样的。
    说明:vuex的数据,每一个组件文件都有很多的数据,如果把所有的数据都放在一个文件中,就会很不好管理。所以需要把vuex数据拆分出来,一个vuex文件管理一个页面中数据。

三、vuex 的 modules 模块化:

          https://vuex.vuejs.org/zh/guide/modules.html(官网,比较详细)  或  https://www.cnblogs.com/superlizhao/p/12012174.html(推荐)

  注意默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。

  • state:Vuex对 modules中的 state 的处理,是直接把模块挂在 父级的 state上的。但是模块下的state数据不用在加state,直接挂在模块属性下。
    const moduleA = {
      state: {
        userMsg: 99
      },
      mutations: {
        cgUserMsg (state, val) {
          state.userMsg = val
        }
      }
    }
    
    
    export default new vuex.Store({
      modules: {
          moduleA 
      }
    })

    获取 moduleA 模块中 store 的数据

    <div>{{$store.state.moduleA.useMsg}}</div>
  • 调用模块内的 action、mutation 和 getter 方法:默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的。所以模块中这些属性 不要 和 父级上这些属性命名相同。
    this.$store.commit('cgUserMsg',45)  // 和调用全局store中的对应方法一样

    执行 mutation 时,会先从父级上找到对应的属性;如果没有的找到时,在从模块中找。

    • getter:
      如果 模块中的 getter 要 拿到 跟节点的 state,可以有第三个参数 rootState。
      const moduleA = {
        // ...
        getters: {
          sumWithRootCount (state, getters, rootState) {
            return state.count + rootState.count
          }
        }
      }
    • action:
  • 命名空间:   默认情况下,模块内部的 action、mutation 和 getter是全局的,如果需要模块具有更高的封装度和复用性,可以给我们设置命名空间。
    参考:使用模块后不借助辅助函数访问数据的方法  https://blog.csdn.net/weixin_43660626/article/details/90448312 
    /* acApply 模块 */
    export default {
      namespaced: true,
      state: {
        userMsg: 99
      },
      mutations: {
        cgUserMsg (state, val) {
          state.userMsg = val
        }
      }
    }
    this.$store.commit('acApply/cgUserMsg',45)   // 调用的时候带上模块名称 
  • Vuex-store 文件夹目录组织:
    将 根  store的getter、mutation、action 分别抽离出来作为单独的文件;模块内的就按一个模块一个文件。

四、使用 Vuex 的辅助函数【推荐https://www.jianshu.com/p/46ed0316c31b  或 https://www.jianshu.com/p/7f790b4188e5 或 https://www.cnblogs.com/padding1015/p/8734031.html 或 https://vuex.vuejs.org/zh/api/#mapstate(官网)

import {mapState,mapGetters,mapActions,mapMutations} from 'vuex'

  1、mapState:将store中state数据映射到组件的计算属性中computed中:映射后,组件通过this.name就可以获取到了。

     注意事项,映射的名称不要和当前组件的data,methods名称发生冲突,否则会被覆盖。

  computed: {
    ...mapState(["name"]), //name和vuex中的state保持一至。直接把vuex中的name映射到当前组件中
  },
 create () {
    console.log(this.name)  // 组件中可以直接通过this获取到vuex里面的state值
  }

  2、mapMutations:把mutations里面的方法映射到methods中

  methods: {
    ...mapMutations(['changeCount']),  // mapMutations映射到组件的methods中
    test () {
      this.changeCount(323)  // 组件中直接使用,vuex中 mutations 里的方法
    }
  }

  3、mapAcions:把actions里面的方法映射到methods中

  4、mapGetters:把getters属性映射到computed身上  

  注意:

    1、this.$store.commit 有两种写法:

        //写法一
        this.$store.commit('add',{n:10})
        //写法二
        this.$store.commit({
            type:'add',
            n:5
        })

    2、getters 和 state 一样都是存储数据的,但是getter的数据通常是对state 数据的二次处理。就是类似计算属性的功能,

       store中getters数据的获取,和state获取挂载的对象不同。这点和组件中的 计算属性有点不同:

this.$store.state.count       // stete中值的获取
this.$store.getters.newCount  // getters 中值的获取

    3、为什么要把  同步  和  异步  区分开:https://www.zhihu.com/question/48759748(看尤雨溪的回答)

       区分 actions 和 mutations  目的是 为了能用 devtools 追踪状态变化。(就是为了便于调试)

  体会:vuex的明显一个作用就是页面间数据变动是同步的。比如,一个页面中有显示支付银行卡的卡号好,还有选择银行卡的按钮。点击选择银行卡的按钮,

    要跳到另外的一个页面中去选择。选好后,跳回来(回退),如果是用vuex的话,之前的页面显示的银行卡号会同步为自己选择的银行卡号

    不然的话就需要先存了缓存(本地存储,或公共变量中),然后在相应的页面中去取。比较麻烦。

五、vuex 使用 模块 后  借助辅助函数访问数据的方法  和  有命名空间 的辅助函数用法:https://vuex.vuejs.org/zh/api/#mapstate(官网中有比较明确的说明)

              

     注意:vuex 使用了 模块,不一定使用了命名空间。默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的。要使用命名空间 需要显示 的配置:

const store = new Vuex.Store({
  modules: {
    account: {
      namespaced: true,   // 显示 设置
      state: { }
    }
  }
})

  1、 vuex 模块 ,但是没有使用命名空间 时,使用辅助函数:

  // 页面中使用 mapState,没有命名空间,就不能使用命名空间。可以使用 es 6的语法简化结构
  ...mapState({
      userInfo: ({ classRoom }) => classRoom.userInfo  // classRoom 是 模块名
    }),

  2、vuex使用命名空间时,使用辅助函数:看官方文档。

六、Vuex规范目录结构:

| - store
   | - actions.js
   | - getters.js
   | - index.js
   | - mutations.js
   | - mutations_type.js  # # 该项为存放 mutaions 方法常量的文件,按需引入。
   |
   | - modules
      | _ Astore.js

说明:1、mutations_type.js 文件(mutations的事件类型,即方法名称)的目的就是为了方便多个地方使用他,可能出现的拼写错误。https://www.jianshu.com/p/9802842448bc/ 

      2、modules 中的 store 一般直接放在一个文件就可以了,如果 Astore 局部模块状态多 也 可以进行细分。

 


视频 听课笔记

1、mutations是唯一一个可以改变vuex状态的方法集。

 

映射到计算属性中computed

posted @ 2018-11-09 18:18  吴飞ff  阅读(331)  评论(0编辑  收藏  举报