想必用過 vue.js 的童鞋,一定知道在 vue 各個組件之間傳值的痛苦,基於父子、兄弟組件,我們傳值可能會很方便,但是如果是沒有關聯的組件之間要使用同一組數據,就顯得很無能為力了,而 vuex 就很好的解決了我們這種問題。所以 Vuex 也是必須掌握的,出去面試也是必問的,那么接下來我們就來簡單介紹下 vuex 是如何來管理組件的狀態的。
官方也有詳細的教程,可以戳這里,但感覺太過於官方了,所以就自己整理了一下
vuex 是 vue 的狀態管理器,存儲的數據是響應式的。但是並不會保存起來,刷新之后就回到了初始狀態,具體做法是在 vuex 里數據改變的時候把數據拷貝一份保存到 localStorage 里面,刷新之后如果 localStorage 里有保存的數據,取出來再替換 store 里的 state。
- 能夠在 Vuex 中集中管理共享的數據,易於開發和后期維護
- 能夠高效的實現組件之間的數據共享,提高開發效率
- 存儲在 Vuex 中的數據都是響應式的,能夠實時保持數據與頁面的同步
- 多個視圖依賴於同一個狀態:例如多組件之間數據共享,在不同頁面都可以拿到用戶信息
- 來自不同視圖的行為需要改變同一個狀態:比如用戶會員信息,在不同頁面可以更改
import Vue from 'vue' import Vuex from 'vuex' // 掛載Vuex Vue.use(Vuex)
3.
const store = new Vuex.Store({ // state 中存放的就是全局共享的數據 state: { count: 0 } }) export default store;
4. 將 store 對象掛載到 vue 實例中
new Vue({ el: '#app', render: h => h(app), router, // 將創建的共享數據對象,掛載到 Vue 實例中 // 所有的組件,就可以從 store 中獲取全局的數據了 store })
// 1. 從vuex中按需導入 mapState 函數
import { mapState } from 'vuex' // 2. 通過剛才導入的 mapState 函數,將當前組件需要的全局數據,映射為當前組件的 computed 計算屬性 computed: { ...mapSate(['count']) }
2. Mutation
Mutation 用於變更 Store 中的數據。
-
- 只能通過 mutation 變更 Store 數據,不可以直接操作 Store 中的數據,通過commit一個mutation來修改,它的本質實際是一個function
- 通過這種方式雖然操作起來稍微繁瑣一些,但是可以集中監控所有數據的變化
- mutation 操作一定是同步的
- 我們每次提交 mutation 都會有一個記錄,Vuex 這樣做是為了更方便的記下每個數據改變的歷史和軌跡,方便監聽以及回滾之類的操作
// 在store.js中定義 mutation const store = new Vuex.Store({ state: { count: 0 }, mutations: { add(state) { state.count++ //變更狀態 } } })
// 在組件中觸發 mutation methods: { handle() { // 觸發 mutations 的第一種方法 this.$store.commit('add') } }
觸發 mutations 時傳遞參數:
// store.js
mutations: { addN(state, step) { //第一個參數是state,后面的參數是 store.commit 傳入的額外參數,即 mutation 的載荷 payload state.count += step } }
// 組件中 this.$store.commit('addN', 3) // 調用commit函數,觸發mutations時攜帶參數
// 1. 從 vuex 中按需導入 mapMutations 函數 import { mapMutations } from 'vuex' // 2. 通過剛導入的 mapMutations 函數,將指定的 mutations 函數,映射為當前組件的 methods 函數 methods: { ...mapMutations(['add', 'addN']) }
注:不要在 mutations 函數中,執行異步操作,比如添加延時器
3. Action
觸發 actions 的第一種方式:
// store.js 中定義 Action const store = new Vuex.store({ //...省略其他代碼 actions: { addAsync(context, payload) { setTimeout(() => { context.commit('add') }, 1000) } } })
// 在組件中觸發 Action methods: { handle() { this.$store.dispatch('addAsync', 3) } }
注:不要在 mutations 函數中,執行異步操作,比如添加延時器
在 actions 中不能直接修改 state 中的數據,必須通過 context.commit 觸發某個 mutation。
context:上下文對象,相當於箭頭函數中的this,和 store 實例具有相同的屬性和方法
// 1. 從 vuex 中按需導入 mapActions 函數 import { mapActions } from 'vuex' // 2. 通過剛導入的 mapActions 函數,將指定的 actions 函數,映射為當前組件的 methods 函數 methods: { ...mapActions(['addAsync', 'addN']) }
4. Getter
Getter用於對Store中的數據進行加工處理形成新的數據。Getter不會修改Store中的原數據,只起到一個包裝器的作用。
-
- Getter 可以對 Store 中已有的數據加工處理之后形成新的數據,類似 Vue 的計算屬性 computed
- 和計算屬性一樣,getter 的返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變才會被重新計算。即 Store 中數據發生變化,Getter 的數據也會跟着變化
// 定義 Getter const store = new Vuex.store({ state: { count: 0 }, getters: { // 實時監聽state值的變化 showNum: state => { return '當前最新的數量是【' + state.count + '】' } } })
使用 getters 的第一種方式:this.$store.getters.名稱
使用 getters 的第二種方式:
import { mapGetters } from 'vuex' computed: { ...mapGetters(['showNum']) }