簡書原文:https://www.jianshu.com/p/0546983f5997javascript
一、什麼是Vuex
二、什麼是「狀態管理模式」?
三、什麼狀況下應該使用 Vuex?
四、Vuex和全局變量的概念區別
五、最簡單的store
六、Vuex的簡單使用
6.一、vue文件版本
6.二、js文件版本html
Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的全部組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。Vuex 也集成到 Vue 的官方調試工具 devtools extension,提供了諸如零配置的 time-travel 調試、狀態快照導入導出等高級調試功能。vue
讓咱們從一個簡單的 Vue 計數應用開始:java
new Vue({ // state data () { return { count: 0 } }, // view template: ` <div>{{ count }}</div> `, // actions methods: { increment () { this.count++ } } })
這個狀態自管理應用包含如下幾個部分:
一、state,驅動應用的數據源;
二、view,以聲明方式將 state 映射到視圖;
三、actions,響應在 view 上的用戶輸入致使的狀態變化。
如下是一個表示「單向數據流」理念的極簡示意:vuex
可是,當咱們的應用遇到多個組件共享狀態時,單向數據流的簡潔性很容易被破壞:
一、多個視圖依賴於同一狀態。
二、來自不一樣視圖的行爲須要變動同一狀態。
對於問題一,傳參的方法對於多層嵌套的組件將會很是繁瑣,而且對於兄弟組件間的狀態傳遞無能爲力。對於問題二,咱們常常會採用父子組件直接引用或者經過事件來變動和同步狀態的多份拷貝。以上的這些模式很是脆弱,一般會致使沒法維護的代碼。vue-cli
所以,咱們爲何不把組件的共享狀態抽取出來,以一個全局單例模式管理呢?在這種模式下,咱們的組件樹構成了一個巨大的「視圖」,無論在樹的哪一個位置,任何組件都能獲取狀態或者觸發行爲!
另外,經過定義和隔離狀態管理中的各類概念並強制遵照必定的規則,咱們的代碼將會變得更結構化且易維護。
這就是 Vuex 背後的基本思想,借鑑了 Flux、Redux、和 The Elm Architecture。與其餘模式不一樣的是,Vuex 是專門爲 Vue.js 設計的狀態管理庫,以利用 Vue.js 的細粒度數據響應機制來進行高效的狀態更新。npm
雖然 Vuex 能夠幫助咱們管理共享狀態,但也附帶了更多的概念和框架。這須要對短時間和長期效益進行權衡。
若是您不打算開發大型單頁應用,使用 Vuex 多是繁瑣冗餘的。確實是如此——若是您的應用夠簡單,您最好不要使用 Vuex。一個簡單的 global event bus 就足夠您所需了。可是,若是您須要構建一箇中大型單頁應用,您極可能會考慮如何更好地在組件外部管理狀態,Vuex 將會成爲天然而然的選擇。app
每個 Vuex 應用的核心就是 store(倉庫)。「store」基本上就是一個容器,它包含着你的應用中大部分的狀態 (state)。Vuex 和單純的全局對象有如下兩點不一樣:
一、Vuex 的狀態存儲是響應式的。當 Vue 組件從 store 中讀取狀態的時候,若 store 中的狀態發生變化,那麼相應的組件也會相應地獲得高效更新。
二、你不能直接改變 store 中的狀態。改變 store 中的狀態的惟一途徑就是顯式地提交 (commit) mutation。這樣使得咱們能夠方便地跟蹤每個狀態的變化,從而讓咱們可以實現一些工具幫助咱們更好地瞭解咱們的應用。框架
/* 安裝 Vuex 以後,讓咱們來建立一個 store。建立過程直截了當——僅須要提供一個初始 state 對象和一些 mutation: */ // 若是在模塊化構建系統中,請確保在開頭調用了 Vue.use(Vuex) const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } } }) /* 如今,你能夠經過 store.state 來獲取狀態對象,以及經過 store.commit 方法觸發 狀態變動: */ store.commit('increment') console.log(store.state.count) // -> 1 /* 再次強調,咱們經過提交 mutation 的方式,而非直接改變 store.state.count,是因 爲咱們想要更明確地追蹤到狀態的變化。這個簡單的約定可以讓你的意圖更加明顯,這樣你 在閱讀代碼的時候能更容易地解讀應用內部的狀態改變。此外,這樣也讓咱們有機會去實現一 些能記錄每次狀態改變,保存狀態快照的調試工具。有了它,咱們甚至能夠實現如時間穿梭般 的調試體驗。 因爲 store 中的狀態是響應式的,在組件中調用 store 中的狀態簡單到僅須要在計算 屬性中返回便可。觸發變化也僅僅是在組件的 methods 中提交 mutation。 */
下載Vuex模塊化
vue-cli搭建的項目 利用腳手架搭建項目以後,能夠經過npm引入vuex npm install vuex
也能夠直接經過引入文件
<script src="/path/to/vue.js"></script>
<script src="/path/to/vuex.js"></script>
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) // 狀態 const state = { count: 0 } const mutations = { INCREMENT (state) { state.count++ }, DECREMENT (state) { state.count-- } } const actions = { increment: ({ commit }) => commit('INCREMENT'), decrement: ({ commit }) => commit('DECREMENT') } const getters = { moreCount: function () { return state.count + 'more' } } export default new Vuex.Store({ state, getters, actions, mutations })
import Vue from 'vue' import App from './App' import store from './store' Vue.config.productionTip = false new Vue({ el: '#app', store, components: { App }, template: '<App/>' })
三、使用store進行狀態管理——計數
3.一、相應點擊事件發佈(dispatch)狀態
<template> <div> <div>{{ msg }}</div><br> <div> <button @click="increment()">+</button> <button @click="decrement()">-</button> </div><br> </div> </template> <script> export default { name: 'HelloWorld', data () { return { msg: 'HelloWorld' } }, methods: { increment () { console.log('+++') this.$store.dispatch('increment') }, decrement () { console.log('---') this.$store.dispatch('decrement') } } } </script> <style scoped> </style>
<template> <div> {{ msg }}<br> {{ count }}<br> {{ moreCount }} </div> </template> <script> export default { name: 'SimpleCounter', data () { return { msg: 'SimpleCounter' } }, computed: { count () { return this.$store.state.count }, moreCount () { return this.$store.getters.moreCount } } } </script> <style scoped> </style>
<html> <meta charset="utf-8"> <head> <title>Test</title> </head> <body> <div id="app"> <p>{{ count }}</p> <p> <button @click="increment">+</button> <button @click="decrement">-</button> </p> </div> <script src="./vue.js"></script> <script src="./vuex.js"></script> <script src="./vuex-demo2.js"></script> </body> </html>
const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment: state => state.count++, decrement: state => state.count-- } }) new Vue({ el: '#app', computed: { count () { return store.state.count } }, methods: { increment () { store.commit('increment') }, decrement () { store.commit('decrement') } } })