原文:intro-to-vue-4-vuex

译者:nzbin

这是关于 JavaScript 框架 Vue.js 五个教程的第四部分。在这一部分,我们会学习使用 Vuex 进行状态管理。这个系列教程并不是一个完整的用户手册,而是通过基础知识让你快速了解 Vuejs 以及它的用途。

Vuex

如果你错过了关于组件及 Vue-cli 的部分,在阅读本篇文章之前应该先读读这几部分。现在我们已经了解了关于组件、传递状态和 props 的基本知识,接下来讨论一下 Vuex,它是状态管理的好工具。

之前,我们是从顶层组件向下传递状态,而同胞组件之间并没有分享数据。如果它们需要相互通信,我们要在应用程序中推送状态。这是可以的!但是一旦你的程序变得复杂,这种方法就没有意义了。如果你之前用过 Redux,那 Vuex 中所有的概念及实现对你也不陌生。Vuex 是 Vue 中的 Redux。实际上,Redux 也可以用于 Vue,但是,使用专门为 Vue 设计的工具 Vuex 更加有利。

首先,安装 Vuex:

npm install vuex

或者

yarn add vuex

我这样设置: 在 `/src` 目录下,我创建了名为 store 的目录 ( 这是一种选择,你也可以在同级目录创建一个 `store.js` 文件 ),再在其中创建一个名为 `store.js`的文件。`store.js` 中的初始设置如下 ( vstore sublime snippet ):

  1. import Vue from 'vue';
  2. import Vuex from 'vuex';
  3.  
  4. Vue.use(Vuex);
  5.  
  6. export const store = new Vuex.Store({
  7. state: {
  8. key: value
  9. }
  10. });

key: value 是状态数据的占位符。在其他例子中,我们已经使用 counter: 0

在 `main.js` 文件中,我们将执行以下更新(加粗显示更新的行):

  1. import Vue from 'vue';
  2. import App from './App.vue';
  3.  
  4. import { store } from './store/store';
  5. new Vue({
  6. el: '#app',
  7. store: store,
  8. template: '<App/>',
  9. components: { App }
  10. });

更新之后,和之前做的组件一样,我们可以把 data() 作为状态,然后我们通过以下三种方式使用或者更新状态:

  • Getters 可以在模板中静态的显示数据。换句话说,getters 可以读取数据,但不能改变状态。
  • Mutations 允许更新状态,但永远是同步的。Mutations 是 store 中改变状态数据的唯一方式。
  • Actions 允许异步更新状态,但是需要使用一个已经存在的 mutation 。如果你需要以特定的顺序同时执行不同的 mutations 会非常有用。

如果你以前没有接触过,也许很难理解为什么会使用异步状态的变化,所以先看看理论上它会发生什么,然后再开始下一部分。假如你运行 Tumblr。如果页面中有大量长时间运行的 gif 图片。你只想每次载入其中一部分,比如当用户将页面滚动到底部 200px 时,加载 20 个图片。

你需要使用 mutation 展示后面的 20 个。但是现在还没有后面的 20 个,你不知道何时到达页面底部。因此,在程序中,创建一个事件来监听滚动的位置然后触发相应的操作。

然后,该操作将从数据库中检索后面 20 个图像的 URL,并将 20 个图片的状态添加到 mutation 中然后显示。

本质上,Actions 创建一个请求数据的框架。它们使用一致的方法来应用异步方式中的数据。

最基本的抽象例子

在下面的例子中,展示了每个属性最基本的实现方式,因此你可以了解如何设置及使用。载荷是可选参数,可以通过它定义正在更新的组件的数值。不用担心,我们随后将演示一个实际案例,现在最重要的是了解基本概念。

`store.js`:

  1. export const store = new Vuex.Store({
  2. state: {
  3. counter: 0
  4. },
  5. // 展示内容, 无法改变状态
  6. getters: {
  7. tripleCounter: state => {
  8. return state.counter * 3;
  9. }
  10. },
  11. // 改变状态
  12. //mutations 永远是同步的
  13. mutations: {
  14. // 显示传递的载荷 payload, 用 num 表示
  15. increment: (state, num) => {
  16. state.counter += num;
  17. }
  18. },
  19. // 提交 mutation, 这是异步的
  20. actions: {
  21. // 显示传递的载荷 payload, 用 asynchNum ( 一个对象 )表示
  22. asyncDecrement: ({ commit }, asyncNum) => {
  23. setTimeout(() => {
  24. // asyncNum 对象可以是静态值
  25. commit('decrement', asyncNum.by);
  26. }, asyncNum.duration);
  27. }
  28. }
  29. });

一个很好的功能是我们可以在 mutations 中返回整个状态对象,但是不必这样做,我们只使用我们需要的。时间穿梭测试(进入 mutations 中寻找错误)仍然可以工作。

在组件中,我们将对 getters 使用 computed (这很重要,因为 value 值已经计算好了),在 methods 中使用 dispatch 来访问 mutations 和 actions

`app.vue`:

  1. computed: {
  2. value() {
  3. return this.$store.getters.value;
  4. }
  5. },
  6. methods: {
  7. increment() {
  8. this.$store.dispatch('increment', 2)
  9. }
  10. }

或者,您可以使用扩展运算符。我发现如果需要大量 mutations/actions 的时候是非常有用的:

  1. export default {
  2. // ...
  3. methods: {
  4. ...mapActions([
  5. 'increment', // 将 this.increment() 映射到 this.$store.commit('increment')
  6. 'decrement',
  7. 'asyncIncrement'
  8. ])
  9. }
  10. }

简单的实例

让我们再看一看天气通知的程序, 在它的 Vuex store 中有少量且简单的状态。这是示例代码的仓库.

See the Pen Vue Weather Notifier by Sarah Drasner (@sdras) on CodePen.

`store.js`:

  1. import Vue from 'vue';
  2. import Vuex from 'vuex';
  3.  
  4. Vue.use(Vuex);
  5.  
  6. export const store = new Vuex.Store({
  7. state: {
  8. showWeather: false,
  9. template: 0
  10. },
  11. mutations: {
  12. toggle: state => state.showWeather = !state.showWeather,
  13. updateTemplate: (state) => {
  14. state.showWeather = !state.showWeather;
  15. state.template = (state.template + 1) % 4;
  16. }
  17. }
  18. });

我们在这里设置了 showWeather 的状态,它的初始值为 false ,因为我们不希望任何动画立即执行,只有当用户点击按钮时才会执行。在 mutations 中,我们可以切换 showWeather 的状态。

我们也将状态中的 template 设置为 0 。我们会在每个天气组件中循环使用这个数字。所以在 mutations 中,我们创建了一个名为 updateTemplate 的方法。它会同时切换 showWeather 的状态并且更新 template 加 1 后的数值,但是值为 4 时再点击会变成 0 。

App.vue:

  1. <template>
  2. <div id="app">
  3. ...
  4. <g id="phonebutton" @click="updateTemplate" v-if="!showWeather">
  5. ...
  6. </g>
  7.  
  8. <transition
  9. @leave="leaveDroparea"
  10. :css="false">
  11. <g v-if="showWeather">
  12. <app-droparea v-if="template === 1"></app-droparea>
  13. <app-windarea v-else-if="template === 2"></app-windarea>
  14. <app-rainbowarea v-else-if="template === 3"></app-rainbowarea>
  15. <app-tornadoarea v-else></app-tornadoarea>
  16. </g>
  17. </transition>
  18. ...
  19.  
  20. </div>
  21. </template>
  1. <script>
  2. import Dialog from './components/Dialog.vue';
  3. ...
  4. export default {
  5. computed: {
  6. showWeather() {
  7. return this.$store.state.showWeather;
  8. },
  9. template() {
  10. return this.$store.state.template;
  11. }
  12. },
  13. methods: {
  14. updateTemplate() {
  15. this.$store.commit('updateTemplate');
  16. }
  17. },
  18. ...
  19. components: {
  20. appDialog: Dialog,
  21. ...
  22. }
  23. }
  24. </script>

`dialog.vue`:

  1. <script>
  2. export default {
  3. computed: {
  4. template() {
  5. return this.$store.state.template;
  6. }
  7. },
  8. methods: {
  9. toggle() {
  10. this.$store.commit('toggle');
  11. }
  12. },
  13. mounted () {
  14. //enter weather
  15. const tl = new TimelineMax();
  16. ...
  17. }
  18. }
  19. </script>

在上面的代码中,App 组件使用了 showWeather 依次展示模板, 而 Dialog 组件只切换组件的可见性。在 App.vue 中,我们根据 App <template> 中的模板数值,通过第一章学过的的条件渲染来展示以及隐藏不同的子组件。在 App 中, 我们通过 computed 数值监听 store 中状态的变化,使用 methods 中的 toggle()updateTemplate() 提交 store 的 mutations 。

这是一个基本示例,但是你可以了解如何处理有大量状态的复杂程序,这有利于在在一个地方管理所有的状态,而不是上下移动组件。尤其当同胞组件之间通信的时候。

如果你想深入了解 Vuex , 可以看这篇 文档 。你肯能注意到我们在最后一个例子中使用了 <transition> 组件,还有大量动画。我们会在下一部分展开讨论。

Vue.js 系列教程 4:Vuex的更多相关文章

  1. Vue.js 系列教程 ②

    这是关于 JavaScript 框架 Vue.js 五个教程的第二部分.在这一部分,我们将学习组件,Props 以及 Slots.这不是一个完整的指南,而是基础知识的概述,所以你可以了解Vue.js ...

  2. Vue.js 系列教程 3:Vue-cli,生命周期钩子

    原文:intro-to-vue-3-vue-cli-lifecycle-hooks 译者:nzbin 这是 JavaScript 框架 Vue.js 五篇教程的第三部分.在这一部分,我们将学习 Vue ...

  3. Vue.js 系列教程 5:动画

    原文:intro-to-vue-5-animations 译者:nzbin 译者的话:经过两周的努力,终于完成了这个系列的翻译,由于时间因素及个人水平有限,并没有详细的校对,其中仍然有很多不易理解的地 ...

  4. Vue.js 系列教程 2:组件,Props,Slots

    原文:intro-to-vue-2-components-props-slots 译者:nzbin 这是关于 JavaScript 框架 Vue.js 五个教程的第二部分.在这一部分,我们将学习组件, ...

  5. Vue.js 系列教程 3:Vue

    原文:intro-to-vue-3-vue-cli-lifecycle-hooks 译者:nzbin 这是 JavaScript 框架 Vue.js 五篇教程的第三部分.在这一部分,我们将学习 Vue ...

  6. Vue.js 系列教程 ①

    原文:intro-to-vue-1-rendering-directives-events 译者:nzbin 如果要我用一句话描述使用 Vue 的经历,我可能会说“它如此合乎常理”或者“它提供给我需要 ...

  7. Vue.js 系列教程 1:渲染,指令,事件

    原文:intro-to-vue-1-rendering-directives-events 译者:nzbin 如果要我用一句话描述使用 Vue 的经历,我可能会说“它如此合乎常理”或者“它提供给我需要 ...

  8. vue.js 系列教程

    Vuejs——(1)入门(单向绑定.双向绑定.列表渲染.响应函数) Vuejs——(2)Vue生命周期,数据,手动挂载,指令,过滤器 Vuejs——(3)计算属性,样式和类绑定 Vuejs——(4)v ...

  9. vue.js和vue-router和vuex快速上手知识

    vue.js和vue-router和vuex快速上手知识 一直以来,认为vue相比react而言,学习成本会更低,会更简单,但最近真正接触后,发现vue的各方面都有做一些客户化的优化,有一些亮点,但也 ...

随机推荐

  1. MySQL远程登陆错误

    远程连接 mySql数据库会提示10061.1045错误或 2003-Can’t connect to MySQL on ’192.168.1.2’(10061),这个原因是因为MySQL不准许远程连 ...

  2. ServiceStack.Redis 使用链接池方法

    PooledRedisClientManager 1.RedisManage.cs public static class RedisManager { private static PooledRe ...

  3. linux 安装jdk及tomcat指定jdk版本推荐

    方法1:用yum命令安装 1.   查看当前jdk版本:Java –version,或者是:rpm -qa | grep jdk 2.   删除当前jdk:yum -y remove java-1.6 ...

  4. iOS 参考 网络书籍

    网络图书: Xcode中的Project和Target: http://book.51cto.com/art/201307/402283.htm

  5. hdu 1005解题报告

    这道题目n的取值范围很大,1 <= n <= 100,000,000.因此肯定是需要优化才能AC. 首先我考虑到时是有没有通项公式,研究了一下,没发现什么东西,突然看到两个1时就想到会不会 ...

  6. OSG开发概览(转载)

    OSG开发概览 1 OSG基础知识 Ø OSG是Open Scene Graphic 的缩写,OSG于1997年诞生于以为滑翔机爱好者之手,Don burns  为了对滑翔机的飞行进行模拟,对open ...

  7. jq动态添加的元素触发绑定事件无效

    <div class='a'> <div class='b'> </div> 其中$('.a')是html页面的元素,$('.b')是jq动态添加的元素.$(&qu ...

  8. 按ctrl + c 播放下一曲音乐

    ./a.out . #include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<dirent. ...

  9. 自定义浏览器滚动条的样式,打造属于你的滚动条风格——兼容IE和webkit(ff不支持)

    前段时间,到网上找素材时,看到了一个很个性的滚动条式,打开Chrome的调试工具看了一下,发现不是用JavaScript来模拟实现的,觉得 有必要折腾一下.于是在各大浏览器中对比了一下,发现只用Chr ...

  10. Thinkphp代码生成工具 ThinkphpHelper

    支持MySQL 和 sqlite数据库,快速构建项目原型,直接生成前后台CRUD代码片段,还可根据需要自行定制代码模板,减少重复劳动. 写这个东西的原因是因为我最近沮丧的发现很多时候我都在做重复的事情 ...