vue2.0探索之路--vuex使用場景和整合
emmm...一直在猶豫要不要寫這篇部落格,因為覺得這些內容官網已經介紹的很詳細了,再複述一遍貌似沒太多意義。後面想了下,不復述、總結,如何加深自己的印象和理解呢,畢竟老年人,記性越來越差了。所以,開始吧。
一、概述
vuex是一個專為Vue.js應用程式開發的狀態管理模式。 它採用集中式儲存管理應用的所有元件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。
二、使用場景
我相信很多人都和我一樣,在使用vuex之前都會想一個問題(如果你一開始就很明確自己對vuex的需求,那麼恭喜你,你很棒棒),為什麼要用vuex????這玩意有啥好的,除了聽著高大上點,狀態管理,那麼具體能給我的專案帶來什麼好處啊,而且我改怎麼用它。下面就來簡單說說我的理解。
狀態管理,就是管理的全域性變數。在我們的專案中,特別是較大型的專案,會有很多引數是很多地方都會用到的,比如,一個登入的token,很多頁面都需要這個資訊,當然我們可以時刻在對應頁面操作cookie,但是有這麼個統一管理的地方,為啥不用呢。所以,狀態管理不是必需的,所有狀態管理能做的,都能用其他方式實現,但是狀態管理提供了統一管理的地方,操作方便,也更加明確。但是別啥都往裡頭扔了,一些只是父元件和子元件用到的,能用$emit和props簡單實現的,就用這個就行了。
三、整合
先貼上我的整合程式碼:
目錄結構
index.js為總入口
getters:state中的狀態獲取
user.js
api中為請求統一封裝
下面開始對vuex的相關功能做個總結,詳情請參考:vuex官網。
1. state
存在mapState輔助函式,見第六小結
import Vue from 'vue'; import App from './App'; import store from './store/index' import './mock/mock'; import router from './router'; import './ui.js' /* 公共服務平臺*/ import 'static/platform/css/common.less'; var vm = new Vue({ el: '#app', router, store, template: '<App/>', components: {App} });
在根元件註冊store之後,可以在元件中通過this.$store.state.count訪問state中的count引數,在模組中,需要在state後面加上模組名,詳情見第五小節。
2.Getter
有時候我們需要從store中的state中派生出一些狀態,可以通過在store中定義getter(可以看作store的計算屬性),Getter接受state作為第一個引數 ,也可以接受其他getter作為第二個引數。存在輔助函式mapGetters,見第六小結
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
}
})
然後可以通過以下方式訪問this.$store.getters.doneTodos
3. Mutation
提交mutation是修改store中的狀態的唯一方法。通過提交mutation,vue能監控到資料的變化,然後動態更新節點。
定義:
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 變更狀態
state.count++
}
}
})
呼叫(可傳入第二個引數作為入參):
store.commit('increment')
物件風格的提交方式:
store.commit({
type: 'increment',
amount: 10
})
也可以使用常量替代Mutation事件型別
//mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION';
// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'
const store = new Vuex.Store({
state: { ... },
mutations: {
// 我們可以使用 ES2015 風格的計算屬性命名功能來使用一個常量作為函式名
[SOME_MUTATION] (state) {
// mutate state
}
}
})
需要注意:Mutation必須是同步函式。
4.Action
Action類似於mutation,不同在於:
1.Action提交的是mutation,而不是直接變更狀態;
2.Action可以包含非同步操作。
示例:
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
action函式接受一個與store例項具有相同方法和屬性的context物件。可以使用引數解構簡化程式碼:
actions: {
increment ({ commit }) {
commit('increment')
}
}
分發Action:
store.dispatch('increment')
非同步操作:
actions: {
checkout ({ commit, state }, products) {
// 把當前購物車的物品備份起來
const savedCartItems = [...state.cart.added]
// 發出結賬請求,然後樂觀地清空購物車
commit(types.CHECKOUT_REQUEST)
// 購物 API 接受一個成功回撥和一個失敗回撥
shop.buyProducts(
products,
// 成功操作
() => commit(types.CHECKOUT_SUCCESS),
// 失敗操作
() => commit(types.CHECKOUT_FAILURE, savedCartItems)
)
}
}
存在mapActions輔助函式,詳見第六小結
5.Module
為了解決store物件隨著專案開發會越來越臃腫,vuex允許將store分割成模組,每個模組擁有自己的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 的狀態
6.輔助函式
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
}
})
}
或者
mapState([
// 對映 this.count 為 store.state.count
'count'
])
物件展開運算子
computed: {
localComputed () { /* ... */ },
// 使用物件展開運算子將此物件混入到外部物件中
...mapState({
// ...
})
}
mapGetters
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// 使用物件展開運算子將 getter 混入 computed 物件中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
}
mapActions
import { mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'increment', // 將 `this.increment()` 對映為 `this.$store.dispatch('increment')`
// `mapActions` 也支援載荷:
'incrementBy' // 將 `this.incrementBy(amount)` 對映為 `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // 將 `this.add()` 對映為 `this.$store.dispatch('increment')`
})
}
}
四、最後
總算總結完了,又加深了一遍記憶,還是很好的。