Vue進階(五):與 Vuex 的第一次接觸
Vue進階(五):與 Vuex 的第一次接觸

在 Vue 項目中,如果項目結構簡單,父子組件之間的數據傳遞可以使用 props 或者 $emit 等方式 (詳參博文《Vue進階(六):組件之間的數據傳遞》)。如果是大型項目,很多時候都需要在子組件之間傳遞數據,使用之前的方式就不太方便。Vue 的狀態管理工具 Vuex 完美的解決了這個問題。
什么是Vuex? 為什么要使用Vuex ?
首先,我們需要知道 vue 是以單向數據流的方式驅動的。
多個視圖依賴于同一狀態。
來自不同視圖的行為需要變更同一狀態。
vuex 類似Redux的狀態管理器, 用來管理Vue的所有組件狀態,采用集中式存儲管理應用的所有組件的狀態,并以相應的規則保證狀態以一種可預測的方式發生變化。
狀態機就是保存你的狀態和狀態變化的一個盒子。這里有一些不同種類的狀態機,適用于我們這個案例的是有限狀態機。像它的名字一樣,有限狀態機包含有限的幾種狀態。它接收一個輸入并且基于這個輸入和當前的狀態決定下一個狀態,可能會有多種情況輸出。當狀態機改變了狀態,我們就稱為它過渡到一個新的狀態
每一個 Vuex 應用的核心就是 store(倉庫)。store基本上就是一個容器,它包含應用中大部分的狀態 (state)。Vuex 和單純的全局對象有以下兩點不同:
Vuex 的狀態存儲是響應式的。當 Vue 組件從 store 中讀取狀態的時候,若 store
中的狀態發生變化,那么相應的組件也會相應地得到高效更新。
你不能直接改變 store 中的狀態。改變 store 中的狀態的唯一途徑就是顯式地提交 (commit) mutation。
這樣使得我們可以方便地跟蹤每一個狀態的變化,從而讓我們能夠實現一些工具幫助我們更好地了解我們的應用。
一、安裝并引入 Vuex
項目結構:
注:當應用變得比較復雜時候,store對象有可能變的相當臃腫。
在此情況下,vuex允許將store分割成模塊(module),每個模塊有自己的state,mutation,action,getter甚至是嵌套子模塊等。
首先使用 npm 安裝 Vuex
cnpm install vuex -S
1
然后在main.js中 引入store.js, 然后注入 store
import Vue from 'vue' import App from './App' import Vuex from 'vuex' import store from './vuex/store' // 讓vue使用vuex工具來實現組件之間的數據共享 Vue.use(Vuex) /* eslint-disable no-new */ new Vue({ el: '#app', // 注入 store store, render: h => h(App) })
1
2
3
4
5
6
7
8
9
10
11
12
13
14
二、構建核心倉庫 store.js
Vuex 應用的狀態 state 都應當存放在 store.js 里面,Vue 組件可以從 store.js 里面獲取狀態,可以把 store 通俗的理解為一個全局變量的倉庫。
但是和單純的全局變量又有一些區別,主要體現在當 store 中的狀態發生改變時,相應的 vue 組件也會得到高效更新。
在 src 目錄下創建一個 vuex 目錄,將 store.js 放到 vuex 目錄下
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const store = new Vuex.Store({ // 定義狀態,存儲數據的對象,我們可以將你需要存儲的數據在這個state中定義 state: { author: 'Wise Wrong' } }) export default store
1
2
3
4
5
6
7
8
9
10
11
12
13
這是一個最簡單的 store.js,里面只存放一個狀態 author。
注:雖然在 main.js 中已經引入了 Vue 和 Vuex,但是這里還得再引入一次.
三、將狀態映射到組件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
這是 footer.vue 的 html 和 script 部分。
在 computed 中,將 this.$store.state.author 的值返回給 html 中的 author。頁面渲染之后,就能獲取到 author 的值。
四、在組件中修改狀態
然后在 header.vue 中添加一個輸入框,將輸入框的值傳給 store.js 中的 author,這里使用 Element-UI 作為樣式框架。
上面將輸入框 input 的值綁定為 inputTxt,然后在后面的按鈕 button 上綁定 click 事件,觸發 setAuthor 方法。
methods: { setAuthor: function () { this.$store.state.author = this.inpuTxt } }
1
2
3
4
5
在 setAuthor 方法中,將輸入框的值 inputTxt 賦給 Vuex 中的狀態 author,從而實現子組件之間的數據傳遞。
五、官方推薦的修改狀態的方式
上面的示例是在 setAuthor 直接使用賦值的方式修改狀態 author,但是 vue 官方推薦使用下面的方法:
首先在 store.js 中定義一個方法 newAuthor,其中第一個參數 state 就是 $store.state,第二個參數 msg 需要另外傳入,然后修改 header.vue 中的 setAuthor 方法。
這里使用 $store.commit 調用mutations中定義的函數 newAuthor,這個函數就是操作state中定義的成員函數,并將 this.inputTxt 傳給 msg,從而修改 author。
你不能直接改變 store 中的狀態。改變 store 中的狀態的唯一途徑就是顯式地提交 (commit) mutation(this.$store.commit(‘mutations方法名’,值))。這樣顯式地提交(commit) mutations,可以讓我們更好的跟蹤每一個狀態的變化,所以在大型項目中,更推薦使用第二種方法。
/ 存儲數據的對象,我們可以將你需要存儲的數據在這個state中定義 const state = { // 當前登陸的用戶名 username: '' } const mutations = { // 提供一個方法,為state中的username賦值 // 這些方法有一個默認的參數,這個參數就是當前store中的State setUserName (state, username) { //存入一個值 state.username = username localStorage.setItem('myname', username) }, getUserName (state) { //輸出一個值 return state.username } } //使用的時候---> 通過commit調用mutations中定義的函數,這個函數就是操作state中定義的成員的函數 // this.$store.commit('setUserName', res.data.username(請求返回的值)) const actions = { setUserNameAction: ({commit}, username) => { commit('setUserName', username) }, getUserNameAction: ({commit}) => { commit('getUserName') } } // 通過action來觸發mutations中的函數,這種觸發方式是異步方式 //存入 this.$store.dispatch('setUserNameAction', res.data.username + 'aa') //取出 this.currentUserName = this.$store.dispatch('getUserNameAction') //Getters是從 store 中的 state 中派生出一些狀態,即當出現多處需要導入某個狀態時,結果不是很理想,所以getters的返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變才會被重新計算。 const getters = { getUserName: (state) => { return localStorage.getItem('myname') } } //使用的時候,直接使用 // 你好:{{$store.getters.getUserName}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
Vue 容器
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。