Vuex的使用以及案例
我們知道組件之間是獨立的,組件之間想要實現通信,我目前知道的就只有props選項,但這也僅限于父組件和子組件之間的通信。如果兄弟組件之間想要實現通信呢?當我們做中大型項目時,面對一大堆組件之間的通信,還有一大堆的邏輯代碼,會不會很抓狂?那為何不把組件之間共享的數據給提取出來,在一定的規則下管理這些數據呢? 這就是vuex的基本思想了。
13.1 Vuex簡介
什么是Vuex?官方說法:Vuex 是一個專為 Vue.js應用程序開發的狀態管理模式。它采用集中式存儲管理應用的所有組件的狀態,并以相應的規則保證狀態以一種可預測的方式發生變化。簡單來說vuex是vue的一個插件,用來實現組件之間數據通訊的。
想要了解Vuex的功能,重點是理解什么是狀態管理,我們這里使用一個計數器的小應用進行知識點的引入。現有一個頁面點擊的計數器,偽代碼如下。
new Vue({
// state
data () {
return {
count: 0
}
},
// view
template: `
`,
// actions
methods: {
increment () {
this.count++
}
}
})
這個小應用中有三個重要的部分:
? state,驅動應用的數據源;
? view,以聲明方式將?state?映射到視圖;
? actions,響應在?view?上的用戶輸入導致的狀態變化。
三個部分組成了一個簡單的計數器,他們之間的關系我們可以叫做“單向數據流”。如圖13.1所示。
圖13.1 單向數據流
state作為我們的數據,展示在view視圖中,視圖中的針對用戶的操作進行相應,調用執行了函數,也就是actions,接下來actions的函數又對我們的數據也就是state進行了改變,在整個流程中三個部分之間的目前來說是一一對應的,也就是說state只顯示在一個view視圖上,也只被一個action的函數所改變,所以稱之為單向數據流。那么如果我們的需求發生了變化,我們不僅僅要在某個頁面進行計數,我們要求這個計數的總數是全局共享的,也就是在所有的頁面中都可以改變state的值。這個時候就出現了一個問題:當我們的應用遇到多個組件共享狀態時,單向數據流的簡潔性很容易被破壞。體現在多個視圖依賴于同一狀態,以及來自不同視圖的行為需要變更同一狀態。
因此,我們為什么不把組件的共享狀態抽取出來,以一個全局單例模式管理呢?在這種模式下,我們的組件樹構成了一個巨大的“視圖”,不管在樹的哪個位置,任何組件都能獲取狀態或者觸發行為,這種模式就是狀態管理。vuex就是vue中實現狀態管理的插件。
13.2 Vuex入門
理解什么是Vuex之后我們直接來上手實際演示一下Vuex如何使用。Vuex的使用場景大多是大型的單頁面應用,因為此時很可能需要使用到組件外部管理狀態。廢話不多說,我們開始學習Vuex的使用。
13.2.1 搭建Vue應用
首先使用vue-cli來構建一個vue的開發環境,項目取名為vuex_demo。這里主要使用的知識點是vue-cli,使用vue create vuex_demo命令完成創建。之前章節已經有過對腳手架的學習,這里不再詳細介紹。
13.2.2 安裝vuex
vuex有多種安裝方式,我們這里介紹其中兩種,分別是直接下載 /CDN 引用,以及nmp命令。實際項目中建議使用命令nmp命令的方式。
? 直接下載 / CDN 引用
在 Vue 之后引入 vuex 會進行自動安裝:
? NPM
npm install vuex --save
進入vuex_demo應用下執行npm install vuex --save命令后,打開package.json文件,在dependencies中找到vuex的依賴就表明安裝成功,如圖13.2所示。
圖13.2 package.json
13.2.3 編寫代碼
我們當前應用完成一個簡單的計數器,頁面中包含當前點擊次數,默認為0,以及一個按鈕,每點擊一次安裝計數器的值加一。
我們在src目錄下新建store文件夾,store表示存儲的意思,我們使用vuex來存儲一些共享的信息。并且在store文件夾中vuex.js文件,此文件用于vuex插件的實例化。Vuex.js文件代碼如例13-1所示。
例13-1 vuex.js
1 //引入模塊
2 import Vue from 'vue'
3 import Vuex from 'vuex'
4 //在一個模塊化的打包系統中,您必須顯式地通過 `Vue.use()` 來安裝 Vuex:
5 Vue.use(Vuex)
6
7 //#實例化Vuex.store ,并進行相關配置
8 export default new Vuex.Store({
9 //存儲狀態
10 state: {
11 count: 0
12 },
13 //其中定義函數,用于變更store中的狀態
14 mutations: {
15 increment (state) {
16 console.log('執行了遞增')
17 state.count++
18 }
19 }
20 })
接下來我們還需要修改main.js文件,在vue實例中添加store選項。main.js文件關鍵代碼如例13-2所示。
例13-2 main.js
1 import Vue from 'vue'
2 import App from './App.vue'
3 //引入vuex.js模塊
4 import Store from './store/vuex'
5
6 Vue.config.productionTip = false
7
8 new Vue({
9 //配置store選項
10 store:Store,
11 render: h => h(App),
12 }).$mount('#app')
最后我們修改App.vue文件,在其中操作如何展示state的值,以及觸發器遞增,App.vue代碼如例12-2所示。
例12-3 App.vue
1
2
3 count:
4
5
{{ $store.state.count }}
6
7
8
9
10
11
12
13
14 export default {
15 name: 'App',
16 methods:{
17 increment:function(){
18 //調用當前vue應用實例的store選項,并且執行函數名為increment的函數
19 this.$store.commit('increment')
20 }
21 }
22
23 }
24
25
26
27 #app {
28 font-family: Avenir, Helvetica, Arial, sans-serif;
29 -webkit-font-smoothing: antialiased;
30 -moz-osx-font-smoothing: grayscale;
31 text-align: center;
32 color: #2c3e50;
33 margin-top: 60px;
34 }
35
36
37
13.2.3 運行項目
運行項目之后可以看到頁面中顯示了定義在store中state里定義的count的值,默認為0,運行效果如圖13.3所示。
圖13.3 運行結果1
在點擊按鈕之后count的值隨著點擊次數遞增并且顯示在頁面中,點擊3次按鈕后效果如果13.4所示。
圖13.4 運行結果2
13.2.4 代碼解釋
以上代碼中關鍵的步驟:
? 使用vuex模塊,初始化Vuex.Store實例,配置state,mutations選項。
? 配置main.js,使全局的vue實例配置store選項,添加對vuex的使用。
? 頁面中應用state的值,已經觸發mutations函數改變state的值。
當然當前的配置并不完整,針對Vuex.store實例化的完整配置如下。
#實例化Vuex.store ,并進行相關配置
export default new Vuex.Store({
state: {
//存儲狀態
},
mutations: {
//變更store中的狀態
},
actions: {
//類似于mutation,
//action提交的是mutation,而不是直接變更狀態
//action可以包含異步操作
},
getters:{
//state的派生狀態
},
modules: {
//將store分割成模塊
}
})
我們發現,在VueX對象中,其實不止有state,還有用來操作state中數據的方法集,以及當我們需要對state中的數據需要加工的方法集等等成員,成員列表:
? state 存放狀態
? mutations state成員操作
? getters 加工state成員給外界
? actions 異步操作
? modules 模塊化狀態管理
成員之間相互配合的流程如圖13.5所示。
圖13.5 vuex流程
首先,Vue組件如果調用某個VueX的方法過程中需要向后端請求時或者說出現異步操作時,需要調用VueX中actions的方法,如果沒有異步操作,那么我們就可以直接在組件內提交狀態中的Mutations中自己編寫的方法來達成對state成員的操作,最后被修改后的state成員會被渲染到組件的位置當中去。
13.3 state訪問狀態對象
state用于存儲共享狀態,我們可以在其中保存共享數據,他是全局的,在任意組件中都可以通過this.$store.state.屬性名獲取對應的狀態數值。
#存儲共享狀態
state:{
num:100,
userinfo:{}
}
#組件中
#通過在根實例中注冊 store 選項,該 store 實例會注入到根組件下的所有子組件中,且子組件能通過 this.$store 訪問到
#由于 Vuex 的狀態存儲是響應式的,從 store 實例中讀取狀態最簡單的方法就是在計算屬性中返回某個狀態
computed:{
num(){
return this.$store.state.num;
}
},
13.4 mutations修改狀態
mutations是操作state數據的方法的集合,比如對該數據的修改、增加、刪除等等。
13.4.1 mutations使用方法
mutations中的方法都有默認的形參:
([state] [,payload])
? state是當前VueX對象中的state
? payload是該方法在被調用時傳遞參數使用的
比如我們剛才寫的案例中,只使用了state一個參數:
//#實例化Vuex.store ,并進行相關配置
export default new Vuex.Store({
//存儲狀態
state: {
count: 0
},
//其中定義函數,用于變更store中的狀態
mutations: {
increment (state) {
console.log('執行了遞增')
state.count++
}
}
})
組件中如果想要改變state中的某個值,不能獲取值之后直接賦值,需要調用mutations中的函數的方式進行對state中值改變的操作。commit中的字符串參數就是mutations中定義的函數的函數名。
this.$store.commit('increment')
13.4.2 mutations傳遞參數
如果我們每次count的值不是遞增,而是指定數值大小的遞增,此時就需要使用額外的參數,此時可以使用payload參數。
vuex.Store初始化部分的代碼如下。
mutations: {
//第二個參數用于傳值
increment (state,payload) {
// 變更狀態
//state.num++
state.num+=payload
}
}
組件中調用代碼如下。
methods:{
increment(){
//第一個參數指定執行mutations中的哪一個函數,第二個參數是執行函數時候傳遞的參數
this.$store.commit('increment',45);
}
}
注意:一條重要的原則就是要記住 mutation 必須是同步函數。
13.5 getters計算過濾操作
有時候我們需要從 store 中的 state 中派生出一些狀態,例如對列表進行過濾并計數。Vuex 允許我們在 store 中定義“getter”(可以認為是 store 的計算屬性)。就像計算屬性一樣,getter 的返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變才會被重新計算。
Getters中的方法有兩個默認參數:
? state 當前VueX對象中的狀態對象。
? getters 當前getters對象,用于將getters下的其他getter拿來用。
比如我們要對保存在state中的student數組數據進行過濾,這返回30歲以下的數據。此時就可以使用getters接受state作為第一個參數,對state中的數據進行過濾,二次處理。
//vuex實例化
getters:{
//過濾年齡小于30
filter_age(state){
return state.student.filter(item => item.age<30);
}
}
//組件中獲取過濾后的數據
//Getters 會暴露為 store.getters 對象,你可以以屬性的形式訪問這些值
this.$store.getters.filter_age
13.6 actions異步修改狀態
actions和之前講的Mutations功能基本一樣,不同點是,actions是異步的改變state狀態,而Mutations是同步改變狀態。
在實例化路由時對actions進行設置語法如下,在actions的函數中調用mutations里的函數。我們會發現這actions和mutations的中的方法傳遞的參數也不一樣,這里是context,表示上下文對象,這里你可以理解稱store本身。
actions: {
increment (context) {
context.commit('increment')
}
}
在組件中調用actions中函數的方式也與mutation調用不同,actions函數執行通過store.dispatch()觸發,調用方式如下。
//Action 通過 store.dispatch 方法觸發:
store.dispatch('increment')
13.7 module模塊組
隨著項目的復雜性增加,我們共享的狀態越來越多,這時候我們就需要把我們狀態的各種操作進行一個分組,分組后再進行按組編寫。module:狀態管理器的模塊組操作。
也就是說由于使用單一狀態樹,應用的所有狀態會集中到一個比較大的對象。當應用變得非常復雜時,store 對象就有可能變得相當臃腫。為了解決以上問題,Vuex 允許我們將 store 分割成模塊(module)。每個模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進行同樣方式的分割:
#moduleA.js
const moduleA = {
state: () => ({ xx }),
mutations: { ... },
actions: { ... },
getters: { ... }
}
export default moduleA;
#modulesB.js
const moduleB = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... }
}
#index.js
import moduleA from './moduleA.js'
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
//使用:this.$store.state.a.xx
13.8 本章小結
? Vuex 是一個專為 Vue.js應用程序開發的狀態管理模式。
? 使用命令npm install vuex --save完成vuex的安裝
? 代碼上vuex中通過實例化Vuex.store ,并進行相關配置來實現狀態管理。
? Vuex 實例化時包含state,mutations,actons,getters,module選項。
? state用于存儲共享狀態,我們可以在其中保存共享數據。在任意組件中都可以通過this.$store.state.屬性名
? mutations是操作state數據的方法的集合,比如對該數據的修改、增加、刪除等等。
? mutations中的方法都有默認的形參:([state] [,payload]),state是當前VueX對象中的state,payload是該方法在被調用時傳遞參數使用的。
? Vuex 允許我們在 store 中定義“getter”屬性來實現對數據的過濾。
? actions和之前講的Mutations功能基本一樣,不同點是,actions是異步的改變state狀態,而Mutations是同步改變狀態。
3.9 理論習題與實踐練
1.思考題
1.1 請簡述你是怎么理解狀態管理的。
1.2 請思考狀態管理的使用場景。
1.3 請簡述vuex的使用步驟。
1.4 請簡述Vue.Store對象實例化所需要的選項都有哪些?
1.5 請簡述如何獲取讀取state中某個數據的值。
1.6 請簡述通過mutations實現對state中數據的值的改變。
2.編程題
? 2.1. 使用vuex實現購物車數據的保存功能
JavaScript Vue
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。