Vue中的Vuex

Posted 飞鹰3995

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue中的Vuex相关的知识,希望对你有一定的参考价值。

小编今天继续和大家一起学习和探讨Vuex,咱们书接上回,继续探索Vuex的其他特性三、Mutation在上一篇文章中,咱们已经知道,对于Vuex中的数据,不能像data中的数据一样直接修改,那要对State中的数据修改的时候,要怎么做呢,Vuex提供了Mutation方式进行统一修改,并且使用state作为第一个参数,就像这样

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // 变更状态
      state.count++
    }
  }
})

要触发这个函数,只需要这样就可以

store.commit(\'increment\')

同样,我们一样可以在提交的时候,多传递一个参数,也就是官网上说的

提交载荷(Payload),就像这样

// ...
mutations: {
  increment (state, n) {
    state.count += n
  }
}
store.commit(\'increment\', 10)

实际上,我们在使用Mutation第二个参数的时候,传递个对象,是平时更常用的方式,同时,也可以传递更大量的数据信息,就像这样

// ...
mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}
store.commit(\'increment\', {
  amount: 10
})

同样,官方还提出了“对象提交风格”,通过type作为作为提交对象的key,对应触发Mutation中对应的方法,就像这样

store.commit({
  type: \'increment\',
  amount: 10
})
mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}

小编在这多说一点,针对对象,js在新的语法中作了很多扩展,其中扩展运算符就是一个,可以合并属性一样的值,同样的,在Linux的一些配置文件中,应该也是使用了类似的思想。

state.obj = { ...state.obj, newProp: 123 }

在实际项目中,对于字符串,我们很容易写错,在之前的文章中,小编提供了两种方案,一种是可以使用es6中的Symbol来实现,一种是可以定义常量来实现,这些在Vuex中也有相应的影子。

// mutation-types.js
export const SOME_MUTATION = \'SOME_MUTATION\'
// store.js
import Vuex from \'vuex\'
import { SOME_MUTATION } from \'./mutation-types\'

const store = new Vuex.Store({
  state: { ... },
  mutations: {
    // 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名
    [SOME_MUTATION] (state) {
      // mutate state
    }
  }
})

对于Mutation,在组件中同样提供了简写方式,和前面的mapGetters类似,提供了mapMutations方式。

import { mapMutations } from \'vuex\'

export default {
  // ...
  methods: {
    ...mapMutations([
      \'increment\', // 将 `this.increment()` 映射为 `this.$store.commit(\'increment\')`

      // `mapMutations` 也支持载荷:
      \'incrementBy\' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit(\'incrementBy\', amount)`
    ]),
    ...mapMutations({
      add: \'increment\' // 将 `this.add()` 映射为 `this.$store.commit(\'increment\')`
    })
  }
}

还有一点值得注意,Mutation必须是同步函数。为什么?请参考下面的例子:

mutations: {
  someMutation (state) {
    api.callAsyncMethod(() => {
      state.count++
    })
  }
}

现在想象,我们正在 debug 一个 app 并且观察 devtool 中的 mutation 日志。每一条 mutation 被记录,devtools 都需要捕捉到前一状态和后一状态的快照。然而,在上面的例子中 mutation 中的异步函数中的回调让这不可能完成:因为当 mutation 触发的时候,回调函数还没有被调用,devtools 不知道什么时候回调函数实际上被调用——实质上任何在回调函数中进行的状态的改变都是不可追踪的。那对于异步函数,怎么处理呢,就到了Vuex中的Actions四、ActionsAction 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态

  • Action 可以包含任意异步操作。

我们先来看一个简单的action

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit(\'increment\')
    }
  }
})

我们在分发action的时候,只需这样就可以了,

store.dispatch(\'increment\')

而且在action内部,是允许进行异步操作的,这也是和mutation不一样的地方,就像这样

actions: {
  incrementAsync ({ commit }) {
    setTimeout(() => {
      commit(\'increment\')
    }, 1000)
  }
}

同样action也支持同样的载荷方式和对象方式进行分发

// 以载荷形式分发
store.dispatch(\'incrementAsync\', {
  amount: 10
})

// 以对象形式分发
store.dispatch({
  type: \'incrementAsync\',
  amount: 10
})

在组件中,也支持简写方式

import { mapActions } from \'vuex\'

export default {
  // ...
  methods: {
    ...mapActions([
      \'increment\', // 将 `this.increment()` 映射为 `this.$store.dispatch(\'increment\')`

      // `mapActions` 也支持载荷:
      \'incrementBy\' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch(\'incrementBy\', amount)`
    ]),
    ...mapActions({
      add: \'increment\' // 将 `this.add()` 映射为 `this.$store.dispatch(\'increment\')`
    })
  }
}

同样,我们在使用action的时候,也可以组合使用,并且结合Promise的特性,还有async和await写出更好更易维护,看着更舒服的代码,就像这样

actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit(\'someMutation\')
        resolve()
      }, 1000)
    })
  }
}
store.dispatch(\'actionA\').then(() => {
  // ...
})
actions: {
  // ...
  actionB ({ dispatch, commit }) {
    return dispatch(\'actionA\').then(() => {
      commit(\'someOtherMutation\')
    })
  }
}

最后,如果我们利用 async / await (opens new window),我们可以如下组合 action:

// 假设 getData() 和 getOtherData() 返回的是 Promise

actions: {
  async actionA ({ commit }) {
    commit(\'gotData\', await getData())
  },
  async actionB ({ dispatch, commit }) {
    await dispatch(\'actionA\') // 等待 actionA 完成
    commit(\'gotOtherData\', await getOtherData())
  }
}

参考文献:https://vuex.vuejs.org/zh/

大家还可以扫描二维码,关注我的微信公众号,蜗牛全栈

以上是关于Vue中的Vuex的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段13——Vue的状态大管家

项目集成 vue-router 和 vuex

Vue 教程(四十九)Vuex 核心概念和项目结构

Vue 教程(四十九)Vuex 核心概念和项目结构

Vue 教程(四十九)Vuex 核心概念和项目结构

Vue 教程(四十九)Vuex 核心概念和项目结构