Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。通俗說Vuex 可以處理共享數據,多個組件同一份數據的操作。
Vuex 也集成到 Vue 的官方調試工具 devtools extension,提供了諸如零配置的 time-travel 調試、狀態快照導入導出等高級調試功能。
每一個 Vuex 應用的核心就是 store(倉庫)。“store”基本上就是一個容器,它包含着你的應用中大部分的狀態 (state)。Vuex 和單純的全局對象有以下兩點不同:
-
Vuex 的狀態存儲是響應式的。當 Vue 組件從 store 中讀取狀態的時候,若 store 中的狀態發生變化,那麼相應的組件也會相應地得到高效更新。
-
你不能直接改變 store 中的狀態。改變 store 中的狀態的唯一途徑就是顯式地提交 (commit) mutation。這樣使得我們可以方便地跟蹤每一個狀態的變化,從而讓我們能夠實現一些工具幫助我們更好地瞭解我們的應用。
- 數據的異步,本地存儲,外部數據的操作,使用 (dispatch) action
定義vuex 調用文件 config.js
import vuex from "vuex"; // 導入 // 安裝 Vue.use(vuex); //創建 var store=new vuex.Store({ state:{ channels:{ data:[], isLoading:false, }, loginUser:[ data:[], isLogin:false, ] } }); export default store;
如果多個數據,模塊定義比較清晰
命名空間:默認情況下,模塊內部的 action、mutation 和 getter 是註冊在全局命名空間的——這樣使得多個模塊能夠對同一 mutation 或 action 作出響應。
// channels.js 文件 export default{ //通過添加 namespaced: true 的方式使其成爲帶命名空間的模塊。當模塊被註冊後,它的所有 getter、action 及 mutation 都會自動根據模塊註冊的路徑調整命名。 namespaced:true,// 開啓命名空間 state:{ data:[], isLoading:false, }, mutations:{ // 唯一可以數據變化的地方,不可有副作用 // state 原來的狀態 payload 負荷 setData(state,payload){ state.data=payload; } }, actions:{ //可有副作用 外部數據,異步,本地存儲 fetchData(context){ // 發送遠程請求獲取數據 var getData=getNewList(); // import getNewList form ../server/new; //context 是當前命名空間, commit 觸發 mutations 裏的方法 , *.vue文件中js調用當前方法 this.$store.dispatch('channels/fetchData'); context.commit("setData",getNewList) } } }; //------------------------------------------------------------------------------------- // config.js 文件, import channels from 'channels' var store=new vuex.Store({ modules:{ //a:channels 或者使用下面的方式,等同於 channels:channels channels } }); export default store;
channels.vue 模板中獲取共享數據
//模板中直接 讀取倉庫數據 {{$store.state.channels.data}} //組件中使用倉庫數據 // 單獨直接調用,比較繁瑣 export default{ computed:{ data(){ return this.$store.state.channels.data } } } // 使用 mapState 輔助函數 處理 屬性 import {mapState} from 'vuex'; // 直接調用 export default{ computed:mapState("channels",["data","isLoading"]); } // 或者 傳一個字符串數組 var computed:mapState("channels",["data","isLoading"]); computed.abc=function(){ result 123; } export default{ computed, } // 或者 對象展開運算符,與局部計算屬性混合使用 export default{ computed:{ ...mapState("channels",["data","isLoading"]), abc(){ return 123; } }, created(){ // 調用更新倉庫數據 命名空間,新的數據 this.$store.commit('channels/setData',[1,2,3]); // 觸發 倉庫 actions this.$store.dispatch('channels/fetchData'); } }
“getter” 對 store 屬性處理
getter 的返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變纔會被重新計算。
const store = new Vuex.Store({ state: { todos: [ { id: 1, text: '...', done: true }, { id: 2, text: '...', done: false } ] }, getters: { // Getter 接受當前 state 作爲其第一個參數 doneTodos: state => { // 處理屬性數據 return state.todos.filter(todo => todo.done) }, // Getter 也可以接受其他 getter 作爲第二個參數 doneTodosCount: (state, getters) => { return getters.doneTodos.length }, // 通過方法訪問 getTodoById: (state) => (id) => { return state.todos.find(todo => todo.id === id) } } }); // *.vue js 中訪問屬性,Getter 會暴露爲 store.getters 對象 store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }] store.getters.doneTodosCount // -> 1 // 在任何組件中使用它 computed: { doneTodosCount () { return this.$store.getters.doneTodosCount } } // 通過方法訪問的調用,注意,getter 在通過方法訪問時,每次都會去進行調用,而不會緩存結果 store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
對於模塊內部的 getter,根節點狀態會作爲第三個參數暴露出來:
const moduleA = { // ... getters: { sumWithRootCount (state, getters, rootState) { return state.count + rootState.count } } }
mapGetters 輔助函數僅僅是將 store 中的 getter 映射到局部計算屬性
// *.vue js 中使用 import { mapGetters } from 'vuex' export default { // ... computed: { // 使用對象展開運算符將 getter 混入 computed 對象中 ...mapGetters([ 'doneTodosCount', 'anotherGetter', // 將一個 getter 屬性另取一個名字,使用對象形式,把 `this.doneCount` 映射爲 `this.$store.getters.doneTodosCount` doneCount: 'doneTodosCount' // ... ]) } }