幾分鐘弄懂Vuex的五大屬性和使用方式
一、Vuex是什么?
介紹:Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式
理解:核心就是 store(倉(cāng)庫(kù)),倉(cāng)庫(kù)是用來干什么的?你就當(dāng)它用來儲(chǔ)存東西的。
二、我們什么時(shí)候應(yīng)該用到Vuex呢?
a.小應(yīng)用不建議使用Vuex,因?yàn)樾№?xiàng)目使用 Vuex 可能會(huì)比較繁瑣冗余;
b.中大型單頁(yè)應(yīng)用,因?yàn)橐紤]如何更好地在組件外部管理狀態(tài),Vuex 將會(huì)成為自然而然的選擇;
三、對(duì)于使用Vuex的理解是什么?
由于Vue是單向數(shù)據(jù)流,子組件內(nèi)部不能直接修改從父級(jí)傳遞過來的數(shù)據(jù),子組件與子組件之間無法相互傳遞數(shù)據(jù)。如果我們想讓兩個(gè)子組件之間進(jìn)行通信的話,可以借助子組件 A 向父組件傳值,父組件接收子組件 A 的數(shù)據(jù)后再傳給 B 組件這樣的方式進(jìn)行通信。
但是這樣會(huì)有一個(gè)問題,就是如果子組件 A 的父組件上面還有一層爺爺組件,或者還有更多祖父類型的層級(jí),那么是不是會(huì)很麻煩。
因此,我們會(huì)想到能不能我們將一個(gè)共有的數(shù)據(jù)存在一個(gè)特定的地方,用的時(shí)候自己去拿,這樣就不需要一層層傳值,于是乎 Vuex 就應(yīng)運(yùn)而生了。
四、vuex由五部分組成(五種狀態(tài)/五種屬性)
state
: 數(shù)據(jù)actions
:可以包含異步操作mutations
: 唯一可以修改state數(shù)據(jù)的場(chǎng)所getters
: 類似于vue組件中的計(jì)算屬性,對(duì)state數(shù)據(jù)進(jìn)行計(jì)算(會(huì)被緩存)modules
:模塊化管理store(倉(cāng)庫(kù)),每個(gè)模塊擁有自己的 state、mutation、action、getter
五、安裝配置
第一步:npm i vuex --save/-S
第二步: 創(chuàng)建store.js
第三步:掛載使用 Vue.use(vuex)
第四步:const store = new Vuex.Store({...配置項(xiàng)})
第五步:導(dǎo)出 export default store
第六步:導(dǎo)入main.js 在根實(shí)例配置 store 選項(xiàng)指向 store 實(shí)例對(duì)象
具體如下
安裝
npm install vuex
創(chuàng)建store.js
// 初始化一個(gè)vuex的實(shí)例(數(shù)據(jù)倉(cāng)庫(kù)) 導(dǎo)出即可 import Vuex from 'vuex' import Vue from 'vue' // 使用安裝 Vue.use(Vuex) // 初始化 const store = new Vuex.Store({ // 配置(state|mutations|actions) }) export default store
把store對(duì)象掛載到Vue實(shí)例中
import store from '@/store' new Vue({ // 把store對(duì)象掛載到vue實(shí)例對(duì)象中,這樣就可以在所有的組件中獲取store中的數(shù)據(jù)了 store, render: h => h(App), }).$mount('#app')
六、詳解五種狀態(tài)
1、state
初始化state
狀態(tài)state用于存儲(chǔ)所有組件的數(shù)據(jù)。
管理數(shù)據(jù)
// 初始化vuex對(duì)象 const store = new vuex.Store({ state: { // 管理數(shù)據(jù) count: 0 } })
在組件獲取state的數(shù)據(jù):原始用法插值表達(dá)式
<div>A組件 state的數(shù)據(jù):{{$store.state.count}}</div> <div>A組件 state的數(shù)據(jù):{{count}}</div>
使用計(jì)算屬性:
// 把state中數(shù)據(jù),定義在組件內(nèi)的計(jì)算屬性中 computed: { // 1. 最完整的寫法 // count: function () { // return this.$store.state.count // }, // 2. 縮寫 count () { return this.$store.state.count } } // 不能使用剪頭函數(shù) this指向的不是vue實(shí)例
注意:
- state中的數(shù)據(jù)是自定義的,但是state屬性名是固定的
- 獲取數(shù)據(jù)可以通過 $store.state
- 可以使用計(jì)算屬性優(yōu)化模板中獲取數(shù)據(jù)的方式
- 計(jì)算屬性不可以使用箭頭函數(shù)(箭頭函數(shù)本身是沒有this的,實(shí)際上用的是父級(jí)函數(shù)中的this)
mapState
目標(biāo):簡(jiǎn)化獲取store數(shù)據(jù)的代碼
把vuex中的state數(shù)據(jù)映射到組件的計(jì)算屬性中。
import { mapState } from 'vuex'
1.使用:mapState(對(duì)象)
// 使用mapState來生成計(jì)算屬性 mapState函數(shù)返回值是對(duì)象 // 使用mapState使用對(duì)象傳參 // computed: mapState({ // // 1. 基礎(chǔ)寫法 (state) 代表就是vuex申明的state // // count: function(state) { // // return state.count // // } // // 2. 使用箭頭函數(shù) // // count: state => state.count // // 3. vuex提供寫法 (count是state中的字段名稱) // count: 'count', // // 4. 當(dāng)你的計(jì)算屬性 需要依賴vuex中的數(shù)據(jù) 同時(shí) 依賴組件中data的數(shù)據(jù) // count (state) { // return state.count + this.num // } // })
2.使用:mapState(數(shù)組)
// 2、mapState參數(shù)是一個(gè)數(shù)組 // computed: mapState(['count', 'total'])
3.如果組件自己有計(jì)算屬性,state的字段映射成計(jì)算屬性
// 3、即在內(nèi)部保留原有的計(jì)算屬性,又要把store中的數(shù)據(jù)映射為計(jì)算屬性 computed: { // 組件自己的計(jì)算屬性 calcNum () { return this.num + 1 }, // 把mapState返回值那個(gè)對(duì)象進(jìn)行展開操作(把對(duì)象的屬性添加到該位置) ...mapState(['count']) }
2、mutations
基本操作
目標(biāo):Vuex規(guī)定必須通過mutation修改數(shù)據(jù),不可以直接通過store修改狀態(tài)數(shù)據(jù)。
為什么要用mutation方式修改數(shù)據(jù)?Vuex的規(guī)定
為什么要有這樣的規(guī)定?統(tǒng)一管理數(shù)據(jù),便于監(jiān)控?cái)?shù)據(jù)變化
定義狀態(tài)修改函數(shù)
// mutations是固定的,用于定義修改數(shù)據(jù)的動(dòng)作(函數(shù)) mutations: { // 定義一個(gè)mutation,用于累加count值 // increment這個(gè)名字是自定義的 increment (state, payload) { // state表示Store中所有數(shù)據(jù) // payload表示組件中傳遞過來的數(shù)據(jù) state.count = state.count + payload }, decrement (state, payload) { state.count = state.count - payload } }
組件中調(diào)用
methods: { handleClick1 () { // 通過觸發(fā)mutation修改state中的count的值 this.$store.commit('increment', 2) }, handleClick2 () { this.$store.commit('decrement', 1) } },
總結(jié):
先定義(mutations),再出發(fā) this.$store.commit(‘mutation的名稱,參數(shù)’)
mutation的本質(zhì)就是方法,方法名稱自定義,mutation函數(shù)內(nèi)部負(fù)責(zé)處理的變更操作。
一種操作就是一個(gè)mutation,不同的mutation處理不同的場(chǎng)景。
mapMutations
- 把vuex中的mutations的函數(shù)映射到組件的methods中
- 通俗:通過mapMutations函數(shù)可以生成methods中函數(shù)
methods: { // 1、對(duì)象參數(shù)的寫法 // ...mapMutations({ // // 冒號(hào)右側(cè)的increment是mutation的名稱 // // 冒號(hào)左側(cè)的increment是事件函數(shù)的名稱,可以自定義 // increment: 'increment' // }) // 2、數(shù)組參數(shù)的寫法(事件函數(shù)名稱和mutation名稱一致) ...mapMutations(['increment']) // 3、這種寫法和第2種等效 // increment (param) { // // 點(diǎn)擊觸發(fā)該函數(shù)后要再次觸發(fā)mutation的 // this.$store.commit('increment', param) // } }
總結(jié):
- mapMutations函數(shù)的作用:簡(jiǎn)化methods的定義
- 原始方式:通過$store.commit方法觸發(fā)mutation
- 簡(jiǎn)寫方式一:對(duì)象寫法
- 簡(jiǎn)寫方式二:數(shù)組寫法
3、action 基本使用
目標(biāo):主要用于處理異步的任務(wù)
安裝axios的包
npm i axios //導(dǎo)入包 import axios from 'axios'
定義獲取數(shù)據(jù)方法
// actions是固定的,用于定義異步操作的動(dòng)作(函數(shù)) actions: { // 定義了一個(gè)action,用于查詢接口數(shù)據(jù) async queryData (context, payload) { console.log(payload) // 調(diào)用接口獲取數(shù)據(jù) const ret = await axios.get('http://test.zjie.wang/tab') // 必須觸發(fā)mutation修改list的值 // context類似于this.$store context.commit('updateList', ret.data.list) } }, mutations: { updateList (state, payload) { state.list = payload } }
組件使用:
methods: { handleQuery () { // 觸發(fā)action(必須調(diào)用dispatch方法) this.$store.dispatch('queryData', 111) } }
mapActions
- mapActions輔助函數(shù),把a(bǔ)ctions中的函數(shù)映射組件methods中
- 通俗:通過mapActions函數(shù)可以生成methods中函數(shù)
// 相當(dāng)于 methods申明了一個(gè)函數(shù)fn(num){ this.$store.dispatch('queryData', num)}? // ...mapActions({ // ? fn: 'queryData' // }) // 相當(dāng)于 methods申明了一個(gè)函數(shù)getData(num){ this.$store.dispatch('getData', num)}? ...mapActions(['queryData'])
總結(jié):
- 原始方式:this.$store.dispatch(‘queryData’, num)
- 簡(jiǎn)化方式一:對(duì)象
- 簡(jiǎn)化方式二:數(shù)組
4、getters用法
目標(biāo):熟悉getters的應(yīng)用場(chǎng)景和具體使用步驟
先定義getters
// 相當(dāng)于state的計(jì)算屬性(基于State處理成另外一份數(shù)據(jù)) // getters的主要應(yīng)用場(chǎng)景:模板中需要的數(shù)據(jù)和State中的數(shù)據(jù)不完全一樣 // 需要基于state中的數(shù)據(jù)進(jìn)行加工處理,形成一份新的的數(shù)據(jù),給模板使用 getters: { ? ? getPartList (state) { ? ? ? ? return state.list.filter(item => { ? ? ? ? ? ? return item.id > 1 ? ? ? ? }) ? ? } }
再使用getters
1.基本使用
caleList () { ? // 注意:獲取getters的值,不需要加括號(hào)(當(dāng)屬性使用) ? return this.$store.getters.getPartList },
2.簡(jiǎn)化用法
import { mapGetters } from 'vuex' // mapGetters的作用:把getters映射為計(jì)算屬性 computed: { ? ? ...mapGetters(['getPartList']), ? ? // ...mapGetters({ ? ? // ? calcList: 'getPartList' ? ? // }), ? ? // calcList () { ? ? // ? // 注意:獲取getters的值,不需要加括號(hào)(當(dāng)屬性使用) ? ? // ? return this.$store.getters.getPartList ? ? // }, }
總結(jié):
- getters相當(dāng)于在State和組件之間添加一個(gè)環(huán)節(jié)(對(duì)state中的數(shù)據(jù)進(jìn)行加工處理后再提供給組件)
- getters不要修改state中的數(shù)據(jù)
- getters類似之前的計(jì)算屬性(基于state中的數(shù)據(jù)進(jìn)行計(jì)算)
5、modules
使用單一狀態(tài)樹,導(dǎo)致應(yīng)用的所有狀態(tài)集中到一個(gè)很大的對(duì)象。但是,當(dāng)應(yīng)用變得很大時(shí),store 對(duì)象會(huì)變得臃腫不堪。
為了解決以上問題,Vuex 允許我們將 store 分割到模塊(module)。每個(gè)模塊擁有自己的 state、mutation、action、getters、甚至是嵌套子模塊——從上至下進(jìn)行類似的分割:
例如:分模塊形式管理數(shù)據(jù),比如user模塊管理用戶信息數(shù)據(jù),cart模塊管理購(gòu)物車數(shù)據(jù),shop模塊管理商品信息數(shù)據(jù)。
import vue from 'vue' import Vuex from 'vuex' Vue.use(vuex); ? const state= ()=>{ token:''} const actions = { ? ?set_token({commit},val){ ? ? ?commit("to_token",val) ? } } const mutations = { ? ?to_token(state,val){ ? ? state.token=val; ? } } const getters = {} ? ? //user模塊 let user = { ? namespaced: true, //一定要開始命名空間。 ? state: { userid: 1234 }, ? actions: { ? }, ? mutations: { ? ? SET_USERID(state, val) { ? ? ? state.userid = val; ? ? } ? }, ? getters: { ? ? } } ? //購(gòu)物車數(shù)據(jù)的模塊 let cart = { ? namespaced: true, ? state: { userid: 567 }, ? actions: { ? ? }, ? mutations: { ? }, ? getters: { ? ? } } ? ? const store = new Vuex.Store({ ? state, ? mutations, ? actions, ? getters, ? modules: { ? ? user, ? ? cart ? }, ? plugins: [createPersistedState({ ? ? storage: sessionStorage, ? ? key: "token" ? })]//會(huì)自動(dòng)保存創(chuàng)建的狀態(tài)。刷新還在 }) ? export default store
home.vue如何使用
獲取user模塊的`userid`
this.$store.state.user.userid this.$store.commit("user/SET_USERID",12345)// 前面是指定模塊user 中的SET_USERID 方法,后面是傳參 可以是對(duì)象、數(shù)組、字符串等
七、數(shù)據(jù)持久化
問題:存儲(chǔ)在vuex中的狀態(tài),刷新頁(yè)面,會(huì)丟失。為了解決刷新頁(yè)面數(shù)據(jù)丟失,才有了數(shù)據(jù)持久化。最簡(jiǎn)單的做法就是利用插件 vuex-persistedState。
1、安裝
cnpm install vuex-persistedState -S
備注:
- -S 是 --save的簡(jiǎn)寫,意為:把插件安裝到 dependencies(生產(chǎn)環(huán)境依賴)中
- -D是 --save-dev的簡(jiǎn)寫,意為:把插件安裝到 devDependencies(開發(fā)環(huán)境依賴)中
2、使用
import createPersistedState from 'vuex-persistedstate' ? const store = new Vuex.Store({ ? state, ? mutations, ? actions, ? getters, ? plugins: [createPersistedState({ ? ? storage: sessionStorage, ? ? key: "token" ? })]//會(huì)自動(dòng)保存創(chuàng)建的狀態(tài)。刷新還在 })
參數(shù):
storage:存儲(chǔ)方式。(sessionStorage,localStarage) key:定義本地存儲(chǔ)中的key
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue+three.js實(shí)現(xiàn)炫酷的3D登陸頁(yè)面示例詳解
這篇文章主要為大家介紹了vue+three.js實(shí)現(xiàn)炫酷的3D登陸頁(yè)面示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07vue3使用Element-plus的el-pagination分頁(yè)組件時(shí)無法顯示中文
本文主要介紹了vue3使用Element-plus的el-pagination分頁(yè)組件時(shí)無法顯示中文,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-12-12Vue文件如何轉(zhuǎn)換成base64并去除多余的文件類型前綴
這篇文章主要介紹了Vue文件如何轉(zhuǎn)換成base64并去除多余的文件類型前綴問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03vuex實(shí)現(xiàn)及簡(jiǎn)略解析(小結(jié))
這篇文章主要介紹了vuex實(shí)現(xiàn)及簡(jiǎn)略解析(小結(jié)),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-03-03vue中關(guān)于redirect(重定向)初學(xué)者的坑
這篇文章主要介紹了vue中關(guān)于redirect(重定向)初學(xué)者的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08