初始vuex
文章目錄
第一步:安裝vuex
-
直接下載或cdn連接
<script src="/path/to/vue.js"></script> <script src="/path/to/vuex.js"></script>
-
通過腳手架直接安裝
vue create projectName
-
創建項目後通過
npm
安裝npm install vuex --save
-
創建項目後使用
yarn
安裝yarn add vuex
-
通過vuex項目自行構建
git clone https://github.com/vuejs/vuex.git node_modules/vuex cd node_modules/vuex npm install npm run build
第二步:瞭解vuex是什麼
vuex 是 專門爲了vue應用程序開發的狀態管理模式
本質:集中式的存儲管理應用到的所有組件的狀態,並讓相應的狀態以可預測的形式發生變化
設計思想:
把項目中全部的組件共享狀態抽取出來,進行一個單例模式管理。
項目中的所有組件樹構成了一個巨大的視圖,無論組件在樹的哪個位置,都能夠獲取到共享狀態的值並觸發相對應的事件。
和定義一個全局變量的區別:
- vuex中存儲的狀態是響應式的,任何一個組件修改了狀態值,在其他組件中都會相應的得到高效更新。
- vuex中儲存的狀態值是不能夠直接修改的。只能夠通過提交mutation進行修改,即不能在組件中隨便定義一個函數對狀態值進行修改。所有能夠使狀態值發生變化的事件都是被定義在store中的。
第三步:開始使用vuex
1、計數器
計數器實例
import Vue from 'vue'
import Vuex from 'vuex'
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
獲取當前狀態的值
store.state.count;
觸發事件變更
store.commit("increment");
2、在vue中注入vuex
通過在根實例中註冊 store
選項,該 store 實例會注入到根組件下的所有子組件中,且子組件能通過 this.$store
訪問到。
注入vuex
Vue.use(Vuex);
new vue({
el:"#app",
store,
})
在子組件中獲取vuex狀態值
this.$store.state.count
第四步:瞭解vuex的核心概念
State
state是什麼
state 是vuex中唯一的一個狀態樹,即單一樹,包含了項目中全部的應用層級的狀態。
state 在vuex中作爲唯一的狀態源而存在
在子組件中如何獲取狀態值
假設你已經通過以上方式將vuex注入到了vue中
this.$store.state.count
在子組件中應該如何展示狀態值
一般情況下,如果我們在子組件中使用狀態值,最簡單的方式是通過計算屬性返回需要的某個狀態,這樣如果狀態發生改變,計算屬性也會相應的發生改變。
學會使用mapState()輔助函數
在開發過程中,如果一個子組件需要使用到多個共享狀態值,爲了減少計算屬性的聲明,可以使用mapState輔助函數進行聲明。
import { mapState } from 'vuex'
-
如果需要給計算屬性重新命名,則mapState接受一個對象
const Counter = { template:`<div>{{count}}</div>`, computed:mapState({ myCount:'count' }) }
-
如果計算屬性名和狀態值的名稱一致,則mapState可以接受一個數組
const Counter = { template:`<div>{{count}}</div>`, computed:mapState([count]) }
-
如果除了狀態值外,該子組件還有其他的計算屬性,則推薦使用對象展開運算符
const Counter = { template:`<div>{{count}}</div>`, computed:{ childData(){ return '計算屬性' }, ...mapState({ //... }) } }
Getter
getter 的使用背景
在多個子組件中,一個計算屬性值依賴相同的多個狀態,或需要對狀態進行相同的處理。類似於以下場景:
computed: {
doneTodosCount () {
return this.$store.state.todos.filter(todo => todo.done).length
}
}
爲此,vuex支持getter屬性,也可以理解爲store中的計算屬性。當getter的依賴值發生改變時,getter就會發生改變。
如何在store中聲明一個計算屬性?
Getter 接受 state 作爲自己的第一個參數
const store = new Vuex.Store({
state: {
// ... 狀態值
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
}
})
如果在Getter中會使用到其他的getter,Getter也支持接受 getter 本身作爲自己的第二個參數
const store = new Vuex.Store({
state: {
// ... 狀態值
},
getters: {
doneTodoCount:state => {
return state.todos.filter(todo => todo.done).length
}
doneTodos: ( state , getters ) => {
return getters.doneTodoCount
}
}
})
如何在組件中使用聲明好的Getter?
通過屬性訪問:getter 在通過屬性訪問時是作爲 Vue 的響應式系統的一部分緩存其中的
computed:{
doneTodoCount(){
return this.$store.getters.doneTodoCount;
}
}
通過方法調用:該方式的前提是,Getter返回的爲一個方法,使用方法調用結果不會作爲緩存,每次調用都會重新執行該方法。
const store = new Vuex.Store({
getters:{
getTodoId:( state ) => (id) => {
return state.todos.find( todo => todo.id === id )
}
}
})
this.$store.getters.getTodoId(2)
同樣被支持的 mapGetters函數
同 mapState 函數一致,在同一個組件中如果需要獲取多個 Getter ,推薦使用 mapGetters 輔助函數,用法同 mapState
Mutation
什麼是Mutation
Mutation 是 vuex 更新狀態值唯一可行的地方。即在子組件中通過提交Mutation從而達到修改state的目的。
在store中的Mutation 更像是組件中的方法,它含有一個字符串的事件類型和一個回調函數。回調函數就是我們修改狀態值的地方。
如何聲明一個Mutation?
聲明方式 和 Getter 一致,並且同樣接受state作爲第一個參數
const store = {
state:{
//...
},
getters:{
//...
},
mutations:{
increment(state){
state.account++;
}
}
}
如何在子組件中提交一個Mutation
this.$store.commit('increment')
如何提交一個帶有參數的Mutation
提交一個帶有參數的 Mutation,在vuex中被稱之爲提交載荷。Mutation接受第二個參數作爲額外的參數,一般來說,載荷(即第二個參數)爲一個對象,方便傳遞更多的數據,也方便代碼的閱讀及維護。
const store = {
state:{
//...
},
getters:{
//...
},
mutations:{
increment(state , payLoad){
state.accout += payLoad.n;
}
}
}
this.$store.commit('increment',{
n:10
})
使用Mutation時一定要注意的地方
-
需要遵守vue的響應規則
(1) 建議在state中初始化好所有的默認值
(2) 當需要在對象上更新屬性時,要遵守vue更新對象的原則
-
Mutation必須是同步函數
同樣被支持的 mapMutations輔助函數
同 Getter 一樣,需要獲取多個Mutation時,建議使用 mapMutations輔助函數,支持傳入數組和對象
Action
Action的產生背景
Action的作用類似於Mutation , 但是又不同於Mutation。因爲在Mutation中只能執行同步操作,且是直接修改了state狀態值。
- Action同樣可以修改狀態值,但是是通過提交Mutation從而達到修改狀態值的目的。
- Mutation只能執行同步操作,而在Action中可以執行任意異步的操作。
如何註冊Action
Action 接受一個和store實例具有相同方法和屬性的context對象參數,可以直接調用commit方法
const store = {
state:{
//...
},
getters:{
//...
},
mutations:{
addCount(state){
state.count++
}
},
actions:{
increment(context){
context.commit('addCount');
}
}
}
在組件中觸發Action
const Count = {
methods:{
addCount(){
this.$store.dispatch('increment');
}
}
}
同樣支持載荷的Action
Action支持接受額外的數據作爲第二個參數,即載荷數據
actions:{
increment(context , payLoad){
context.commit('addCount' , payLoad);
}
}
const Count = {
methods:{
addCount(){
this.$store.dispatch('increment'.{
count:10
});
}
}
}
一般什麼條件下會使用Action
當我們需要一些異步操作及提交多個Mutation時,我們可能會需要是要Action,尤其是異步操作。
以下爲官方購物車案例:
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輔助函數
import { mapActions } from 'vuex'
export default {
methods: {
...mapActions([
'increment',
'incrementBy'
]),
...mapActions({
add: 'increment'
})
}
}
Module
產生背景
當我們使用單一的文件樹時,整個store文件就容易變得很龐大複雜。使用Module的目的就是爲了使store更加便於管理。
每個模塊有屬於自己的state、Setter、Mutation、Action等屬性,單獨的模塊也可以再向下分子模塊。
如何定義新的模塊
const moduleA = {
state:{},
setters:{},
mutations:{},
actions:{}
}
const moduleB = {
state:{},
setters:{},
mutations:{},
actions:{}
}
const store = new Vuex.Store({
modules:{
a:moduleA,
b:moduleB
}
})
如何在子模塊訪問根節點和局部狀態值
-
Mutation 和 Getter 訪問局部狀態
Mutation 和 Getter 接受到的第一個參數 state 就是當前子模塊的局部狀態
-
Action 訪問局部狀態 和 根節點
Action 接受 具有store 實例方法和屬性的 context 對象爲第一個參數,context對象中的state指當前子模塊的局部狀態,context對象中rootState獲取的是根節點中的state值
-
Getter 訪問根節點
Getter中 第一個參數爲 當前子模塊的state值、第二個參數爲當前子模塊的Getter值,第三個參數爲根節點 rootState
更加具有複用性的命名空間
默認情況下,模塊內部的屬性都是註冊在全局狀態下的,方便在發生修改時直接觸發。但是爲了模塊的更加封閉性及可複用性,你可以通過添加 namespaced: true
的方式使其成爲帶命名空間的模塊。
如何在具有命名空間的模塊內訪問全局內容
-
在Getter 和 Mutation 中使用全局狀態
在一個子模塊中,Getter/Mutation 接受到的參數爲( 當前子模塊的state、當前子模塊的getters、根節點狀態rootState、根節點getters:rootGetters )
-
在Action中使用全局狀態
rootState 和 rootGetters 會通過context 暴露在子模塊中.
如何在子模塊中分發全局內容
在 commit 和 dispatch 中 將 { root:true } 設置爲第三個參數,例如在b模塊中派發A模塊中的action
dispatch('a/getCount', null, { root: true })
如何在組件中訪問子模塊的狀態及提交事件
在子組件中訪問子模塊的state狀態和Getter
const Count = {
computed:{
count(){
return this.$store.state.a.count;
},
getTodos(){
return this.$store.getters.a.todos;
}
}
}
在子組件中提交事件
const Count = {
methods:{
add(){
this.$store.commit('a/add' ,{
count:10
} )
}
}
}
在模塊中使用輔助函數
在輔助函數中,可以將模塊的命名作爲第一個參數傳遞給函數,這樣在第二個函數中自動綁定該模塊。