原文:intro-to-vue-4-vuexcss
译者:nzbinhtml
这是关于 JavaScript 框架 Vue.js 五个教程的第四部分。在这一部分,咱们会学习使用 Vuex 进行状态管理。这个系列教程并非一个完整的用户手册,而是经过基础知识让你快速了解 Vuejs 以及它的用途。vue
若是你错过了关于组件及 Vue-cli 的部分,在阅读本篇文章以前应该先读读这几部分。如今咱们已经了解了关于组件、传递状态和 props 的基本知识,接下来讨论一下 Vuex,它是状态管理的好工具。git
以前,咱们是从顶层组件向下传递状态,而同胞组件之间并无分享数据。若是它们须要相互通讯,咱们要在应用程序中推送状态。这是能够的!可是一旦你的程序变得复杂,这种方法就没有意义了。若是你以前用过 Redux,那 Vuex 中全部的概念及实现对你也不陌生。Vuex 是 Vue 中的 Redux。实际上,Redux 也能够用于 Vue,可是,使用专门为 Vue 设计的工具 Vuex 更加有利。github
首先,安装 Vuex:vuex
npm install vuex
数据库
或者npm
yarn add vuex
app
我这样设置: 在 `/src` 目录下,我建立了名为 store 的目录 ( 这是一种选择,你也能够在同级目录建立一个 `store.js` 文件 ),再在其中建立一个名为 `store.js`的文件。`store.js` 中的初始设置以下 ( vstore sublime snippet ):框架
import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); export const store = new Vuex.Store({ state: { key: value } });
key: value
是状态数据的占位符。在其余例子中,咱们已经使用 counter: 0
。
在 `main.js` 文件中,咱们将执行如下更新(加粗显示更新的行):
import Vue from 'vue'; import App from './App.vue'; import { store } from './store/store'; new Vue({ el: '#app', store: store, template: '<App/>', components: { App } });
更新以后,和以前作的组件同样,咱们能够把 data()
做为状态,而后咱们经过如下三种方式使用或者更新状态:
若是你之前没有接触过,也许很难理解为何会使用异步状态的变化,因此先看看理论上它会发生什么,而后再开始下一部分。假如你运行 Tumblr。若是页面中有大量长时间运行的 gif 图片。你只想每次载入其中一部分,好比当用户将页面滚动到底部 200px 时,加载 20 个图片。
你须要使用 mutation 展现后面的 20 个。可是如今尚未后面的 20 个,你不知道什么时候到达页面底部。所以,在程序中,建立一个事件来监听滚动的位置而后触发相应的操做。
而后,该操做将从数据库中检索后面 20 个图像的 URL,并将 20 个图片的状态添加到 mutation 中而后显示。
本质上,Actions 建立一个请求数据的框架。它们使用一致的方法来应用异步方式中的数据。
在下面的例子中,展现了每一个属性最基本的实现方式,所以你能够了解如何设置及使用。载荷是可选参数,能够经过它定义正在更新的组件的数值。不用担忧,咱们随后将演示一个实际案例,如今最重要的是了解基本概念。
`store.js`:
export const store = new Vuex.Store({ state: { counter: 0 }, // 展现内容, 没法改变状态 getters: { tripleCounter: state => { return state.counter * 3; } }, // 改变状态 //mutations 永远是同步的 mutations: { // 显示传递的载荷 payload, 用 num 表示 increment: (state, num) => { state.counter += num; } }, // 提交 mutation, 这是异步的 actions: { // 显示传递的载荷 payload, 用 asynchNum ( 一个对象 )表示 asyncDecrement: ({ commit }, asyncNum) => { setTimeout(() => { // asyncNum 对象能够是静态值 commit('decrement', asyncNum.by); }, asyncNum.duration); } } });
一个很好的功能是咱们能够在 mutations 中返回整个状态对象,可是没必要这样作,咱们只使用咱们须要的。时间穿梭测试(进入 mutations 中寻找错误)仍然能够工做。
在组件中,咱们将对 getters 使用 computed
(这很重要,由于 value 值已经计算好了),在 methods
中使用 dispatch
来访问 mutations 和 actions:
`app.vue`:
computed: { value() { return this.$store.getters.value; } }, methods: { increment() { this.$store.dispatch('increment', 2) } }
或者,您可使用扩展运算符。我发现若是须要大量 mutations/actions 的时候是很是有用的:
export default { // ... methods: { ...mapActions([ 'increment', // 将 this.increment() 映射到 this.$store.commit('increment') 'decrement', 'asyncIncrement' ]) } }
让咱们再看一看天气通知的程序, 在它的 Vuex store 中有少许且简单的状态。这是示例代码的仓库.
See the Pen Vue Weather Notifier by Sarah Drasner (@sdras) on CodePen.
`store.js`:
import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); export const store = new Vuex.Store({ state: { showWeather: false, template: 0 }, mutations: { toggle: state => state.showWeather = !state.showWeather, updateTemplate: (state) => { state.showWeather = !state.showWeather; state.template = (state.template + 1) % 4; } } });
咱们在这里设置了 showWeather
的状态,它的初始值为 false ,由于咱们不但愿任何动画当即执行,只有当用户点击按钮时才会执行。在 mutations 中,咱们能够切换 showWeather
的状态。
咱们也将状态中的 template
设置为 0 。咱们会在每一个天气组件中循环使用这个数字。因此在 mutations 中,咱们建立了一个名为 updateTemplate
的方法。它会同时切换 showWeather
的状态而且更新 template
加 1 后的数值,可是值为 4 时再点击会变成 0 。
App.vue:
<template> <div id="app"> ... <g id="phonebutton" @click="updateTemplate" v-if="!showWeather"> ... </g> <transition @leave="leaveDroparea" :css="false"> <g v-if="showWeather"> <app-droparea v-if="template === 1"></app-droparea> <app-windarea v-else-if="template === 2"></app-windarea> <app-rainbowarea v-else-if="template === 3"></app-rainbowarea> <app-tornadoarea v-else></app-tornadoarea> </g> </transition> ... </div> </template>
<script> import Dialog from './components/Dialog.vue'; ... export default { computed: { showWeather() { return this.$store.state.showWeather; }, template() { return this.$store.state.template; } }, methods: { updateTemplate() { this.$store.commit('updateTemplate'); } }, ... components: { appDialog: Dialog, ... } } </script>
`dialog.vue`:
<script> export default { computed: { template() { return this.$store.state.template; } }, methods: { toggle() { this.$store.commit('toggle'); } }, mounted () { //enter weather const tl = new TimelineMax(); ... } } </script>
在上面的代码中,App 组件使用了 showWeather
依次展现模板, 而 Dialog 组件只切换组件的可见性。在 App.vue 中,咱们根据 App <template>
中的模板数值,经过第一章学过的的条件渲染来展现以及隐藏不一样的子组件。在 App 中, 咱们经过 computed
数值监听 store 中状态的变化,使用 methods 中的 toggle()
和 updateTemplate()
提交 store 的 mutations 。
这是一个基本示例,可是你能够了解如何处理有大量状态的复杂程序,这有利于在在一个地方管理全部的状态,而不是上下移动组件。尤为当同胞组件之间通讯的时候。
若是你想深刻了解 Vuex , 能够看这篇 文档 。你肯能注意到咱们在最后一个例子中使用了 <transition>
组件,还有大量动画。咱们会在下一部分展开讨论。