近期的項目中屢次用到了Vuex,感受對Vuex不太熟悉,趁着週末學習了一波,如今來總結一下。javascript
官網Vuex 是什麼? | Vuex (vuejs.org)的描述vue
Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的全部組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。java
我的理解vuex就是一個用來共享數據的,在Vuex裏存的數據全部的組件均可以訪問到,而沒必要進行復雜的組件通信。git
vuex的核心就是state,getters,mutations,actions,modules這5個核心概念。github
安裝vuex
# yarn $ yarn add vuex # or npm $ npm i vuex
在store/index.js中代碼shell
import Vue from 'vue' import Vuex from 'vuex' import moduleA from './module/a' Vue.use(Vuex) export default new Vuex.Store({ state: { msg: 'goodnight everyone!!' }, mutations: { }, actions: { }, getters: { }, modules: { moduleA, } })
在main.js中npm
import Vue from 'vue' import App from './App.vue' import store from './store' Vue.config.productionTip = false new Vue({ // 給Vue實例注入store,在組件中能夠經過this.$store訪問到Vuex的數據 store, render: h => h(App) }).$mount('#app')
最後在任意組件中,均可以經過this.$store來訪問Vuex中的store數組
如:在App.vue中promise
<template> <div id="app"> {{ $store.state.msg }} </div> </template> <script> export default { name: 'App' } </script>
當咱們想要修改state中的數據時,須要提交mutation來修改
mutations: { SET_MSG: (state, value) => { state.msg = value } }, // 在vue文件中 this.$store.commit('SET_MSG', 'xxxxx')
若是須要進行一些異步的操做,則mutation就不行了,須要在action中來提交mutation
actions: { setMsg: ({commit}, value) => { commit('SET_MSG', value) // 還能夠返回commit的結果,這是一個promise對象 return commit('SET_MSG', value) // Promise } } // 在vue文件中 this.$store.dispatch('setMsg', 'xxxxx') // 若是action中return了mutation的commit,那麼就能夠進行.then 或者await操做 this.$store.dispatch('setMsg', 'xxxxx').then(() => { // ... }) // 或者在一個async 修飾的異步函數中使用await await this.$store.dispatch('setMsg', 'xxxxx')
當一個組件須要獲取多個狀態的時候,將這些狀態都聲明爲計算屬性會有些重複和冗餘。爲了解決這個問題,咱們能夠使用 mapState
輔助函數幫助咱們生成計算屬性
// 在單獨構建的版本中輔助函數爲 Vuex.mapState import { mapState } from 'vuex' export default { // ... computed: mapState({ // 箭頭函數可以使代碼更簡練 count: state => state.count, // 傳字符串參數 'count' 等同於 `state => state.count` countAlias: 'count', // 爲了可以使用 `this` 獲取局部狀態,必須使用常規函數 countPlusLocalState (state) { return state.count + this.localCount } }) }
當映射的計算屬性的名稱與 state 的子節點名稱相同時,咱們也能夠給 mapState
傳一個字符串數組
computed: mapState([ // 映射 this.count 爲 store.state.count 'count' ])
利用展開運算符與局部計算屬性混合使用
computed: { localComputed () { /* ... */ }, // 使用對象展開運算符將此對象混入到外部對象中 ...mapState({ // ... }) }
和mapState使用方法同樣
和mapState用法相似,只不過是將mutations或actions映射成methods
methods: { ...mapActions([ // 映射 this.setMsg('xxx') 爲 store.$dispatch('setMsg', 'xxx') 'setMsg' ]), ...mapMutations([ // 映射this.SET_MSG('xxx') 爲store.commit('SET_MSG', 'xxx') 'SET_MSG' ]) }
緣由:
store裏的數據是保存在運行內存中的,當頁面刷新時,頁面會從新加載vue實例,store裏面的數據就會被從新賦值初始化
解決方法一:
利用sessionStorage或localStorage或者或cookie進行緩存,beforeunload事件能夠在頁面刷新前觸發,監聽beforeunload事件,在app.vue的生命週期中進行store中數據的存儲和初始化,這裏以存在sessionStorage中爲例
export default { name: 'App', created () { // 在頁面加載時讀取sessionStorage裏的狀態信息 if (sessionStorage.getItem('vuex')) { this.$store.replaceState(Object.assign({}, this.$store.state, JSON.parse(sessionStorage.getItem('vuex')))) } // 在頁面刷新時將vuex裏的信息保存到sessionStorage裏 window.addEventListener('beforeunload', () => { sessionStorage.setItem('vuex', JSON.stringify(this.$store.state)) }) } }
解決方法二:
利用第三方庫,vuex-persistedstate進行Vuex數據的持久化。
安裝
$ yarn add vuex-persistedstate
在vuex初始化時候,做爲組件引入。
import persistedState from 'vuex-persistedstate' export default new Vuex.Store({ // ... plugins: [persistedState()] })
默認是持久化全部的state,也能夠自行配置
能夠參考這兩個連接:vuex持久化 vuex-persistedstate - 簡書 (jianshu.com)
假設store/index.js中代碼以下
import Vue from 'vue' import Vuex from 'vuex' import persistedState from 'vuex-persistedstate' export default new Vuex.Store({ state: { msg: 'hello vuex', userInfo: { username: '', password: '' } }, mutations: { SET_MSG: (state, value) => { state.msg = value }, SET_USER_INFO(state, value) => { state.userInfo = value } }, actions: { setUserInfo: ({commit}, value) { commit("SET_USER_INFO", value) } } plugins: [persistedState()] })
<script> import { mapState, mapActions, mapMutations } from 'vuex' export default { computed: { ...mapState(['userInfo']), // 和簡單數據類型進行綁定,須要提供setter,在setter中(分發actions)提交mutation修改state msg: { get() { return this.$store.state.msg } set(value) { this.SET_MSG(value) } } }, // 和複雜數據類型進行綁定,須要深度監聽,在handler中(分發actions—)提交mutation修改state watch: { userInfo: { handler(userInfo) { this.setUserInfo(userInfo) }, deep: true } }, methods: { ...mapActions(['setUserInfo']), ...mapMutations['SET_MSG'] } </script>