发表于: 2019-11-07 21:34:31

1 1148


今天完成的事情:

1.学习了vuex:

1,核心概念

1.1 State: 用于数据的存储,是store中的唯一数据源,类似vue中data对象.

  • 单一状态树:用一个对象就包含了所有应用层级状态.每个应用就只包含一个store实例.
  • 计算属性:由于Vuex的状态储存是响应式的,从store实例中读取状态最简单的方法就是在计算属性中返回某个状态(例如token).
  • 使用方法:
// 定义 new Vuex.Store({     state: {         bilibili: { acFun:"我还想再活五百年" }     }     //... }) // 组件中获取 this.$store.state.bilibili.acFun 复制代码

Tips:如果某个state是作为公共状态给多个组件使用,且不想被修改后污染其他组件.这时可以将state写成return形式,类似vue中data一样.(仅2.30+以上支持)

    state(){ return{ bilibili: { acFun:"我还想再活五百年" } }     } 复制代码

1.2 Module: 将store分割成不同的模块,方便管理维护

  • 可以将store分割成模块(module).每个模块拥有自己的state,mutation,action,getter,甚至嵌套子模块--从上至下进行同样的方式的分割.
  • 使用方法:
// 定义 const moduleA = {     state: { ... },     mutations: { ... },     actions: { ... },     getters: { ... } } const moduleB = {     state: { ... },     mutations: { ... },     actions: { ... } } const store = new Vuex.Store({     modules: {         a: moduleA,         b: moduleB     } }) // 组件中使用 store.state.a // -> moduleA 的状态 store.state.b // -> moduleB 的状态 复制代码

1.3 Getter: 对共享数据进行过滤获取

  • 当需要对 store 中的数据进行处理,或者数据被多个组件复用,就可以使用 Getters 来处理,Getters 也可以理解为 Vue 中的计算属性 (computed),其实就是基于state数据的再包装
  • getter的返回值会根据它的依赖被缓存起来.
  • 使用方法:
// 定义,第一个参数为该模块下的state;第二个参数getters为store里的getters.注意getters是没有按模块进行区分的;第三个参数rootState顾名思义就是根state getters: {     cartProducts(state, getters, rootState)          => (getters.allProducts.filter(p => p.quantity)), dateFormat(state, getters) {             let date = state.nowDate;             return `${date.getFullYear()}-${date.getMonth()+1}-${date.getDate()} / ${date.getHours()}:${date.getMinutes()}`;         } } // 组件中获取 this.$store.getters.cartProducts //补充:由于getters会缓存结果.如果你不想缓存,或者想对getters进行传参,此时则需要用函数形式写getter. getters:{ //... test:(state)=>(param)=>{ return state.todos.find(todo=>todo.id===id) } } 复制代码

1.4 Mutation: 改变state的唯一方法

  • 每个mutation都有一个字符串的事件类型(type) 和一个 回调函数
  • mutation必须是同步函数
  • mutation不能包含异步操作
  • 由于store中状态是响应式的,那么在修改时,mutation也应该满足vue响应式的一些注意事项:
    • 最好提前在你的 store 中初始化好所有所需属性。
    • 当需要在对象上添加新属性时,你应该
      • 使用 Vue.set(obj, ‘newProp’, 123),或者
      • 以新对象替换老对象.例如,利用 stage-3 的对象展开运算符我们可以这样写:
 state.obj = { ...state.obj, newProp: 123 } 复制代码
  • mutation是修改state的唯一方法,并且mutations不能直接调用,而要通过相应type调用store.commit.
  • 使用方法:
// 定义 第一个参数state为该模块下的state;第二个参数products为调用时的传参 mutations: {     setProducts (state, products) {         state.allProducts = products     } } // 组件中提交方式可以分为三种,其实前两种都是载荷(payload),第三种是对象形式 //第一种 直接在后面加上要传入的参数 this.$store.commit('setProducts', 'GodOfWar4') //第二种 直接在后面加上要传入的参数 this.$store.commit('setProducts', { name:'GodOfWar4', comment:"我TM射爆!" }) //注意:此时mutation,setProducts 就要修改为下面形式 setProducts (state, products) {         state.allProducts = products.name //要改为这种写法     } //第三种 将state类别作为对象的属性,和参数一起提交 this.$store.commit({ type:'setProducts', name:'GodOfWar4', comment:"我TM射爆!" }) //此时mutation的写法和第二种情况一样. 复制代码

1.5 Action: 可以使用异步操作提交mutation

  • action提交的是mutation,而不是直接变更状态.action可以包含异步操作
  • action通过store.dispatch触发(异步)
  • action返回的是promise
  • 如果是state的数据就使用actions请求数据,建议数据处理也放在actions中,或者放在getter中进行数据处理.mutations只做state的修改.
  • 使用方法:
      state: {          count: 0              },       mutations: {                          increment (state) {           state.count++          }           },       actions: {         //只是提交`commit`了`mutations`里面的方法。          increment (context,payload) {           context.commit('increment')     }    }  // 一般我们会通过解构简写成这样   actions: {    increment ({ commit },payload) {          commit('increment')       }          } // 在组件中使用,同mutation,只是由commit变为dispatch this.$store.dispatch('increment', {//..payload}) //这里需要说明的是第一个参数context就是上下文,context是一个store对象,你也可以用解构的方式写出来,第二个参数payload是我们的传参,同mutation一样. //那么context究竟包含了哪些?通过源码可以清楚看到: let res = handler({     dispatch,    commit,    getters: store.getters,    state: getNestedState(store.state, path),    rootState: store.state   }, payload, cb) //可以看出context包括5个属性:dispatch,commit,getters,state,rootState. //故我们可以通过解构的方式{commit,dispatch,state}只取我们需要的属性. 复制代码
  • 组合 Action (完全照搬官网说明)

Action 通常是异步的,那么如何知道 action 什么时候结束呢?更重要的是,我们如何才能组合多个 action,以处理更加复杂的异步流程?

首先,你需要明白 store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise,并且 store.dispatch仍旧返回 Promise

actions: {   actionA ({ commit }) {     return new Promise((resolve, reject) => {       setTimeout(() => {         commit('someMutation')         resolve()       }, 1000)     })   } } 复制代码

现在你可以:

store.dispatch('actionA').then(() => {   // ... }) 复制代码

在另外一个 action 中也可以:

actions: {   // ...   actionB ({ dispatch, commit }) {     return dispatch('actionA').then(() => {       commit('someOtherMutation')     })   } } 复制代码

最后,如果我们利用 async / await,我们可以如下组合 action:

// 假设 getData() 和 getOtherData() 返回的是 Promise actions: {   async actionA ({ commit }) {     commit('gotData', await getData())   },   async actionB ({ dispatch, commit }) {     await dispatch('actionA') // 等待 actionA 完成     commit('gotOtherData', await getOtherData())   } } 复制代码

一个 store.dispatch 在不同模块中可以触发多个 action 函数。在这种情况下,只有当所有触发函数完成后,返回的 Promise 才会执行。

Tips:

  • 有一点要注意的是,将 store 中的 state 绑定到 Vue 组件中的 computed 计算属性后,对 state 进行更改需要通过 mutation 或者 action,在 Vue 组件中直接进行赋值 (this.myState = ‘ABC’) 是不会生效的。

  • 在 Vuex 模块化中,state 是唯一会根据组合时模块的别名来添加层级的,后面的 getters、mutations 以及 actions 都是直接合并在 store 下。

  • 由于vuex是单向数据流,vue中v-model是双向绑定.所以当v-model绑定的数据时vuex时,需要监听实时修改vuex中的数据.


明天计划:

1.把vuex运用到页面数据里,进行页面数据跨组件共享。



返回列表 返回列表
评论

    分享到