翻译进度
12
分块数量
7
参与人数

Vuex 入门 —— 使用 Vuex 来管理你的 Vue.js 应用状态
5

这是一篇协同翻译的文章,你可以点击『我来翻译』按钮来参与翻译。

file

如果你做过大型的单页应用,你对『状态管理』的概念肯定会很熟悉。尤其是你如果使用过 Facebook 的 Redux 架构 Redux。在这篇文章里,我将带你了解下如果在 Vue 中使用 Vuex 来实现类似的设计模式。

alex 翻译于 4个月前

准备

按照

Vuex 虽然是 Vue 官方的包,但是其并没有内置。你需要自己决定 你的应用中是否会用到它,然后使用 Yarn 或者 NPM 进行安装。

# Yarn 的方式
$ yarn add vuex
# NPM 的方式
$ npm install vuex --save

接下来在你的应用初始化代码那,开启 Vuex 插件:

main.js

import Vue from 'vue';
import Vuex from 'vuex';
import App from 'App.vue';

Vue.use(Vuex);

new Vue({
  el: '#app',
  render: h => h(App)
});
alex 翻译于 4个月前

新建一个 Store

在开始之前,你需要创建一个 Vuex Store。Store 是一个全局的响应式对象,这遵循了 Vue 一般的响应式模式。它无法被直接读取或者修改,这样保证了状态的一致性,并且跟踪其状态改变也会变得相对简单。请见下面代码:

store.js

export const store = new Vuex.Store({
  state: {
    safelyStoredNumber: 0
  }
});
alex 翻译于 4个月前

现在你可以在你所有的模块中通过 import 来导入,或者你可以将其注入 Vue 的全局根对象以此在所有模块中都可以通过 this.$store 直接读取到。在接下来的其余文章里,我们都将统一使用第二种方法。

main.js

import Vue from 'vue';
import Vuex from 'vuex';
import App from 'App.vue';
import { store } from './store.js';

Vue.use(Vuex);

new Vue({
  store,
  el: '#app',
  render: h => h(App)
});
alex 翻译于 4个月前

访问状态

现在的 Store 不能做任何事情。它是一个独立的状态盒子,用于防止你的行为被意外的读取和操作,要从 Store 读取数据,你需要创建一个Getter。

使用 Getters

Getters 仅仅是存储在一个函数中的状态,它接收一个状态对象并从组件中返回一个值。属性作为其计算属性,而不是函数。如果一个 Getter 需要一个参数,它可以返回一个带第二个参数的函数。
store.js

export const store = new Vuex.Store({
  state: {
    safelyStoredNumber: 0
  },
  getters: {
    safelyStoredNumber: state => state.safelyStoredNumber,
    storedNumberMatches(state) {
      return matchNumber => {
          return state.safelyStoredNumber === matchNumber;
      }
    }
    // 简写方法:
    // storedNumberMatches: state => matchNumber => state.safelyStoredNumbers === matchNumber
  }
});
weixia942 翻译于 4个月前

然而,访问组件中的 getters 的简单方法是通过 Vuex 的 mapGettershelper 方法。 这使你可以将 getter 安装到组件中的顶级计算属性。

如果你想重命名组件中的 gettermapGetters 可以获取一个对象。

App.vue

<template>
  <p>The safely stored number: {{safelyStoredNumber}}<p>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  computed: {
    ...mapGetters([
      // 将 “safelyStoredNumber” getter 加载到组件的作用域。
      'safelyStoredNumber'
    ])
  }
}
</script>
Ellison 翻译于 3个月前

修改 State 状态

同步 Mutations

在 Vuex 中,如果需要直接修改state的状态,可以通过一个叫 mutation的函数。mutation 传递当前的状态和一个可选的负载 。 有效负载可以是任何对象。 Mutations 必须是同步的,不应有返回值。 可以直接使用 this.$store.commit('mutationName', payload)来运行。
store.js

export const store = new Vuex.Store({
  state: {
    safelyStoredNumber: 0
  },
  ...
  mutations: {
    incrementStoredNumber(state) {
      state.safelyStoredNumber++;
    },
    setStoredNumber(state, newNumber) {
      // newNumber 是传入的有效负载
      state.safelyStoredNumber = newNumber;
    }
  }
});
simple_ 翻译于 3个月前

与 Getters 一样,Vuex也为组件中的 Mutations 提供了一种方便的方法,即 MapMutations 辅助方法。这使您可以将 Mutations 作为组件中的方法进行使用。
App.vue

<template>
  <p>The safely stored number: {{safelyStoredNumber}}<p>
</template>

<script>
import { mapMutations } from 'vuex'

export default {
  ...
  methods: {
    ...mapMutations([
      // 将  "incrementStoredNumber" 转变为 `this.incrementStoredNumber()`.
      'incrementStoredNumber',
      // 将 "setStoredNumber" 转变为 `this.setStoredNumber(newNumber)`.
      'setStoredNumber'
    ])
  }
}
</script>
weixia942 翻译于 3个月前

Asynchronous Actions

在更复杂的应用中,你很可能要用到一些异步功能去修改状态,Vuex则运用actions去处理,状态应该同时定义在你的state对象里,传达至整个状态上下文。状态允许通过getters和commit去修改。async方法期望(但不必要)返回一个promise的标识完成状态。使用ES2017的async/await,你可以写出十分简洁但不易于理解的异步actions。Actions用在components中的写法是: this.$store.dispatch('actionName', payload).then(response => {})

store.js

import myRemoteService from './my-remote-service.js'

export const store = new Vuex.Store({
  state: {
    safelyStoredNumber: 0
  },
  ...
  actions: {
    async setNumberToRemoteValue(context) {
            // 不论myRemoteService.getRemoteValue()通过promise返回的结果是什么,都提交setStoredNumber修改状态。
      context.commit('setStoredNumber', await myRemoteService.getRemoteValue());
      return Promise.resolve();
    },
  }
});
ZX0086AEC 翻译于 2个月前

If you're not familiar with async / await, seriously, go read about it. It's awesome. The short of it is, it pauses the execution of the current function until the awaited promise resolves, allowing you to essentially use promise resolutions as variables without all the extra boilerplate normally needed.

The Vuex convenience method for actions, (predictably named mapActions) is used in the same way as the one for mutations.

App.vue

<template>
  <p>The safely stored number: {{safelyStoredNumber}}<p>
</template>

<script>
import { mapActions } from 'vuex'

export default {
  ...
  methods: {
    ...mapActions([
      // Mounts the "setNumberToRemoteValue" action to `this.setNumberToRemoteValue()`.
      'setNumberToRemoteValue',
    ])
  }
}
</script>

Modularizing

A single store is fine if you're only working with a small set of data, but inevitably at some point you'll want to split your constantly-growing list of actions, mutations, and getters into separate sections. Thankfully Vuex provides a system to do this as well. Modules. Despite the scary name, a module is simply a normal object with state, getters, mutations, and actionsproperties. You can easily create one by doing this:

my-store-module.js

export const myModule = {
  // This makes your getters, mutations, and actions accessed by, eg: 'myModule/myModularizedNumber' instead of mounting getters, mutations, and actions to the root namespace.
  namespaced: true,
  state: {
    myModularizedNumber: 0
  },
  getters: {
    myModularizedNumber: state => state.myModularizedNumber
  },
  mutations: {
    setModularizedNumber(state, newNumber) {
      state.myModularizedNumber = newNumber
    }
  }
}

store.js

import { myModule } from './my-store-module.js';

export const store = new Vuex.Store({
  modules: {
    myModule
  },
  state: {
    safelyStoredNumber: 0
  },
  ...
});

你可以按需将模块嵌套在模块中,另外,mapGetters,mapMutations,和 mapActions 都可以在第一个参数中传入一个命名空间,这样你就可以不必像下面这样写代码了:

...mapGetters([
  'myModule/nestedModule/subNestedModule/exampleGetter',
  'myModule/nestedModule/subNestedModule/anotherGetter',
])

你可以像这样传入参数:

...mapGetters('myModule/testedModule/subNestedModule', [
  'exampleGetter',
  'anotherGetter'
])

希望该文章能帮助你了解 Vuex 状态管理!

科大大 翻译于 4个月前

本文章首发在 Vuejs 知识社区
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

参与译者:7
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

  • 请注意单词拼写,以及中英文排版,参考此页
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
  • 支持表情,使用方法请见 Emoji 自动补全来咯,可用的 Emoji 请见 :metal: :point_right: Emoji 列表 :star: :sparkles:
  • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif
  • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
  请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!