原文: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>
組件,還有大量動畫。咱們會在下一部分展開討論。