Vuex入门介绍
Vuex 是什么?
Vuex 是一個專為 Vue.js 應用程序開發的狀態管理模式。它采用集中式存儲管理應用的所有組件狀態,并以相應的規則保證狀態以一種可預測的方式發生變化。
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
https://www.jianshu.com/p/5624362cd1f4--出處
看完這段專業的解釋,我反正是一臉懵逼,內心毫無波瀾,甚至有點想吃醬肘子。感覺和沒說一樣嘛!keep going。
什么是"狀態管理模式"?
一個簡單Vue計數器應用
new Vue({// state data () {return {count: 0}},// view template: `<div>{{ count }}</div> `,// actions methods: {increment () {this.count++}} })這個狀態自管理應用包含以下幾個部分:
- state,驅動應用的數據源;
- view,以聲明方式將 state 映射到視圖;
- actions,響應在 view 上的用戶輸入導致的狀態變化。
這是一種“單向數據流”的理念。
然后說明一下這種理念的缺點,當我們的應用遇到多個組件共享狀態時,單向數據流的簡潔性很容易被破壞:
- 多個視圖依賴于同一狀態。
- 來自不同視圖的行為需要變更同一狀態。
這里說的是,vue 組件之間的傳值操作,組件不多的情況下,嵌套的父子組件(prop,emit,on)和兄弟組件(global event bus)還容易操作一些。但是如果項目龐大,組件結構復雜,組件間的數據傳遞會變得很困難,后期代碼不易維護。
看到這里,貌似明白了些這鬼東西是要解決什么問題了。好的,然后我們繼續往“坑”里走。
最簡單的store
每一個 Vuex 應用的核心就是 store(倉庫)。“store”基本上就是一個容器,它包含著你的應用中大部分的狀態 (state)。Vuex 和單純的全局對象有以下兩點不同:
- Vuex 的狀態存儲是響應式的。當 Vue 組件從 store 中讀取狀態的時候,若 store 中的狀態發生變化,那么相應的組件也會相應地得到高效更新。
- 你不能直接改變 store 中的狀態。改變 store 中的狀態的唯一途徑就是顯式地提交 (commit) mutation。這樣使得我們可以方便地跟蹤每一個狀態的變化,從而讓我們能夠實現一些工具幫助我們更好地了解我們的應用。
現在,你可以通過 store.state 來獲取狀態對象,以及通過 store.commit 方法觸發狀態變更:
store.commit('increment'); // 觸發修改變量的方法 console.log(store.state.count); // -> 1WTF?這是啥,這不就是“全局變量”嘛!多個組件可能用到的數據,存儲到?store(倉庫)里,但是這些數據是響應式的,所以對這些數據進行操作時,要遵守相應的規則。例如上面的例子。對?count?進行修改,要通過?commit?來觸發?mutation?里的方法對數據進行操作。
好了,喝口我的枸杞大補茶壓壓驚 [ 微笑 ]。從這里再往坑里走,才是 Vuex 的一些核心概念,他們是:?
- State
- Getter
- Mutation
- Action
- Module
讓我們開始吧。
State
Vuex 使用單一狀態樹,用一個對象就包含了全部的應用層級狀態。至此它便作為一個“唯一數據源 (SSOT)”而存在。這也意味著,每個應用將僅僅包含一個 store 實例。單一狀態樹讓我們能夠直接地定位任一特定的狀態片段,在調試的過程中也能輕易地取得整個當前應用狀態的快照。
這段話說的是一個 Vuex 只能包含一個store(存儲數據的庫),這樣你在訪問數據的時候好找些。
store 的其中一個配置項就是 state 。這個state吧,可以把他比作成vue實例中的data選項,就是把數據放在這里面。
獲取商品列表?this.$store.state.shopList?就能看到了,或者使用輔助函數mapState,這樣雖然方便簡單,建議新手先研究一下 es6 和方法原理,這里不做解釋。
computed: mapState([// 映射 this.shopList為 store.state.shopList'shopList' ])Vuex?文檔中有很多?es6?語法,如果有還不了解的同學們,可要抓緊上車嘍。
Getter
我一度懷疑是不是文檔寫錯了,少加了一個s。(Getters)
這一項從字面意思上就可以看出,他是用來取數據,得到數據的。有人會問,為什么不直接用this.$store.state.shopList這種方式直接拿呢。這種方式確實可以拿到,但是經常會有一些情況是對拿到的數據做一些處理,例如格式化、過濾數據。。。這時候就會用到 Getter 了。
使用this.$store.getters.shopid2得到五菱宏光,即可加入秋名山車神爭霸,走上人生巔峰。
輔助函數?mapGetters?方法:
Mutation
更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation。Vuex 中的 mutation 非常類似于事件:每個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數 (handler)。這個回調函數就是我們實際進行狀態更改的地方,并且它會接受 state 作為第一個參數:
const store = new Vuex.Store({state: {count: 1},mutations: {increment (state) {// 變更狀態state.count++}} })你需要以相應的 type 調用 store.commit 方法:this.$store.commit('increment')
你想要動我的數據,就得守我 Vuex 的規矩(順我者昌,逆我者亡)。
拿數據用 Getters ,改數據用 mutation 。這個 mutation 有點像 vue 的生命周期鉤子函數,里面是一些方法,通過 this.$store.commit(typeName) 對應的函數名稱,觸發對應的函數。
提交載荷(Payload)
你可以向 store.commit 傳入額外的參數,即 mutation 的 載荷(payload):
// ... mutations: {increment (state, n) {state.count += n} } store.commit('increment', 10);// 在大多數情況下,載荷應該是一個對象,這樣可以包含多個字段并且記錄的 mutation 會更易讀 mutations: {increment (state, payload) {state.count += payload.amount} } store.commit('increment', {amount: 10 })?輔助函數?mapMutations?方法:
import { mapMutations } from 'vuex'export default {// ... methods: {...mapMutations(['increment', // 將 `this.increment()` 映射為 `this.$store.commit('increment')`// `mapMutations` 也支持載荷:'incrementBy' // 將 `this.incrementBy(amount)` 映射為 `this.$store.commit('incrementBy', amount)` ]),...mapMutations({add: 'increment' // 將 `this.add()` 映射為 `this.$store.commit('increment')` })} }在 Vuex 中,mutation 都是同步事務:
store.commit('increment') // 任何由 "increment" 導致的狀態變更都應該在此刻完成。為了處理異步操作,讓我們繼續往下走 。
Action
Action 類似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接變更狀態。
- Action 可以包含任意異步操作。
也就是說,Action 執行的還是 Mutation ,只不過他可以異步執行,差不多就是給 Mutation 外邊包了一層函數。
乍一眼看上去感覺多此一舉,我們直接分發 mutation 豈不更方便?實際上并非如此,還記得 mutation 必須同步執行這個限制么?Action 就不受約束!我們可以在 action 內部執行異步操作: actions: {incrementAsync ({ commit }) {setTimeout(() => {commit('increment'); // 在異步函數成功后調用 Mutation}, 1000)} }通過?this.$store.dispatch('incrementAsync')即可調用。
輔助函數?mapActions?方法
Module
由于使用單一狀態樹,應用的所有狀態會集中到一個比較大的對象。當應用變得非常復雜時,store 對象就有可能變得相當臃腫。為了解決以上問題,Vuex 允許我們將 store 分割成模塊(module)。每個模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進行同樣方式的分割: const moduleA = {state: { ... },mutations: { ... },actions: { ... },getters: { ... } }const moduleB = {state: { ... },mutations: { ... },actions: { ... } }const store = new Vuex.Store({modules: {a: moduleA,b: moduleB} })store.state.a // -> moduleA 的狀態 store.state.b // -> moduleB 的狀態 Module 的意思也不難理解,如果你有很多的狀態,都寫在一起會比較亂,后邊也不好改,你就可以給他們分個類,比如 moduleA 是我的購物車模塊的狀態管理,moduleB 是我的商品信息模塊的狀態管理。
對于大型應用,我們會希望把 Vuex 相關代碼分割到模塊中。下面是項目結構示例: ├── index.html ├── main.js ├── api │ └── ... # 抽取出API請求 ├── components │ ├── App.vue │ └── ... └── store├── index.js # 我們組裝模塊并導出 store 的地方├── actions.js # 根級別的 action├── mutations.js # 根級別的 mutation└── modules├── cart.js # 購物車模塊└── products.js # 產品模塊
什么時候用 Vuex?
這個嘛,很簡單。你覺得你的項目里,各組件之間傳參什么的,相處的很和諧,那就無所謂用不用了。
當你的組件兄弟們有傳參問題,有很多這個組件要用,那個組件要,其他好幾個組件也要,要的你生不如死,你就可以考慮一下了。
總結
最后,我們再回顧一下?Vuex?都包含什么,是做什么用的。
store
俗稱倉庫,倉庫里是你的模塊的數據、數據狀態、對數據做的操作,都在這個倉庫里。
?state
倉庫里的數據都放到這個里面,很像?vue 的 data?。
?
getters
通常獲取可以用?this.$store.state.shopList?就可以拿到,但是如果你想對這項數據加工一下(格式化、過濾),就在 getters 里處理,然后通過?this.$store.getters.eventName?獲取。
?
mutation
修改數據操作,你想對某項數據進行修改,就得守規矩。不能用?this.$store.state.count=99,要把修改函數寫在 mutation 里面,用?this.commit('eventName')?觸發修改函數。注意,這里的操作必須是同步。
?
action
異步觸發 mutation 。
?
module
給多個狀態模塊分類。
?
轉自:?https://www.jianshu.com/p/5624362cd1f4
?
轉載于:https://www.cnblogs.com/Vayne-N/p/11089824.html
總結
- 上一篇: flask基础(上篇)
- 下一篇: 美好生活从java开始