Vuex初体验

写在前面

作为一个Vue用户,大家想必已经厌倦了props、bus的复杂和繁琐。所以今天我们来体会一下Vuex,在降低耦合度的同时还增加了代码的可维护性。可谓是一举两得。同时由于其简单的语法和较少的内容,也适合大多数使用vue-cli的童鞋

准备

在安装之前建议你们去chrome商城中找一个名为“Vue.js devtools”的插件,可以跟踪数据的变化。

开始

state

使用Vuex的时候,我们必须先引入一个概念:“仓库

  • 顾名思义,store即容器,包含你应用中的状态(state)。而state中存储的则是我们希望共享的变量
const store = new Vuex.Store({
  state: {
    count: 0
  }
})

而在.Vue文件中我们可以通过computed属性来获取store中定义的变量

const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return store.state.count
    }
  }
}

每当store.state.count发生变化我们都会重新求取computed的值并触发更新相关的DOM

getters
  • 还有一个问题:我们可以添加数据,可以处理数据,但谁来获取?总不能你窝里一顿操作人家外边照样风平浪静吧?所以我们再引入一个新的属性:getters
getters: {
    // getter接受state作为其第一个参数(毕竟返还的也是state中定义的对象)
    getNum(state) {
        return state.num
    }
}

getters中的方法可以将数据返还给组件,以完成通信。我们可以在.vue文件中通过this.$store.getters.method完成对应值的获取

computed:{
    appShowNum(){
      return this.$store.getters.getNum
    }
}

//我们可以理解为,Getter会暴露名为store.getters的对象。我们可以通过属性的形式访问这些值

就像计算属性一样 getter的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

getter我们可以将其理解为是store的计算属性。其返回值就像computed一样,会被缓存起来,只有发生改变时才会重新被计算

mutaions
  • 只有数据当然远远无法满足我们的要求啦,Vuex同样贴心的给我们提供了另一个工具:mutations。此工具用以实现对数据的操作。后边我们还要介绍一个名为actions的属性,他们俩的区别就是:mutaions必须是同步处理方式

我们来举个例子

mutations: {
    // payload是一个对象,官方文档称其为“载荷”
    addNum(state, payload) {
        state.num += payload.num
    }
},

可以看到,我们可以传入一个对象payload,按照此题来看也就是一个具有num属性的对象。

当然,还有另外一个要注意的点:我们不能直接调用一个mutaion函数,而是要走一个流程:store.commit('functionName')

扫描二维码关注公众号,回复: 4734388 查看本文章
actions
  • 异步怎么办?

上边我们说到Vue.js devtools对于mutaions只能检测到其同步请求,而对于异步请求则无法同步快照(没记录,只有结果)。但是我们的项目中更多的是异步操作。比如我们在数据同步的时候需要后台给我们发送的数据,故需要异步的ajax请求,数据返回的时候才能完成加载。这时候我们就可以用到新的属性:actions

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    // payload是一个对象,官方文档称其为“载荷”
    addNum(state, payload) {
      state.num += payload.num
    }
  },
  actions: {
    // 此处有异步,但没有关系,可以记录快照
    addNumByServerRate(store, payload) {
      setTimeout(() => {
        // 后台比例是1
        let rate = 2
          // 最终还是通过mutations更改数据
          //使用store.commit方法触发状态的变更
          store.commit('addNum', { num: payload.num * rate })
        }, 1000)
    }
  }
})

要注意两点:

  • Acion提交的是mutataion,而非直接变更状态
  • Action可以包含任意异步操作
分发Acion

作为action的一个重要的方法,dispatch主要用来将action中的方法分发到mutation中去。只有如此,action的异步方法才可以在mutation中调用

哪里能用到呢?才疏学浅,还是举一个官方文档给的例子吧

actions: {
  checkout ({ commit, state }, products) {
    // 把当前购物车的物品备份起来
    const savedCartItems = [...state.cart.added]
    // 发出结账请求,然后乐观地清空购物车
    commit(types.CHECKOUT_REQUEST)
    // 购物 API 接受一个成功回调和一个失败回调
    shop.buyProducts(
      products,
      // 成功操作
      () => commit(types.CHECKOUT_SUCCESS),
      // 失败操作
      () => commit(types.CHECKOUT_FAILURE, savedCartItems)
    )
  }
}

这是一个购物车示例。我们异步调用了typesCHECKOUT_REQUESTAPI,同时还做了分发多重mutation

再结合ES6的awaitasync

// 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才会执行。

Module模块化

由于Vuex使用单一状态树,所以随着应用的增大,store对象也会变得相当臃肿。所以我们不妨将store分割成一个个的模块,并令其拥有自己的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 的状态

至于模块内部,state则指向了模块本身,即,此state是模块的局部状态,故不用担心混淆。若涉及到多层嵌套则可以通过rootState来完成查询

这里不同的方法有不同的默认接收参数

  • mutation(state)
  • getter(state)
  • action(state, commit, rootState)
  • getter(state, getters, rootState)
    用的时候注意区分,别搞混了

猜你喜欢

转载自blog.csdn.net/qq_38722097/article/details/84671200