vuex的计算属性_Vuex详细介绍
1. 什么是Vuex
Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。這是官網(wǎng)的說法,其實(shí)很簡單:就是一個(gè)加強(qiáng)版的data! 在單頁應(yīng)用中會(huì)有一個(gè)data函數(shù),里面就存放了當(dāng)前頁面的一些數(shù)據(jù)。比如:
{{num}}
export default {
data(){
return {
num:'99'
}
}
}
代碼中的data就相當(dāng)于我們這里描述的Vuex。 如果我們的頁面比較簡單,切記千萬不要沒事找事引入Vuex,我們使用Vuex是因?yàn)轫?xiàng)目變得復(fù)雜之后,有很多數(shù)據(jù)需要在父組件、子組件和孫組件之間傳遞,處理起來很繁瑣,于是就需要Vuex這樣一個(gè)可以對(duì)這一部分?jǐn)?shù)據(jù)進(jìn)行統(tǒng)一管理的東西。
2. 全局data就行了,非要這么復(fù)雜?
對(duì)于我剛剛提到的需求:處理大量的需要在組件間傳遞的數(shù)據(jù),直接定義一個(gè)全局的data屬性保存就行了,比如這樣:this.$root.$data。為什么還要搞一個(gè)這么復(fù)雜的狀態(tài)管理? 如果我們按照剛剛所說的搞一個(gè)全局變量存放數(shù)據(jù)其實(shí)也行,但是這樣有一個(gè)問題,就是數(shù)據(jù)改變后,不會(huì)留下變更過的記錄,這樣不利于調(diào)試。 所以我們稍微搞得復(fù)雜一點(diǎn)。我們約定組件不能直接修改屬于store實(shí)例的state,組件必須通過Mutation來改變state,也就是說,組件里面應(yīng)該執(zhí)行分發(fā)(dispatch)事件通知store去改變。這樣約定的好處是,我們能夠記錄所有store中發(fā)生的state改變,同時(shí)實(shí)現(xiàn)能做到記錄變更、保存狀態(tài)快照、歷史回滾/時(shí)光旅行的先進(jìn)的調(diào)試工具。
3. 先來一個(gè)簡單的State
知道了個(gè)大概,那我們就實(shí)際操作一遍,感覺一下這個(gè)聽起來很牛逼的東西用起來到底怎么樣。 我們使用vue-cli腳手架生成一個(gè)Vue項(xiàng)目,并且安裝Vuex,最終的項(xiàng)目結(jié)構(gòu)是這樣的:
我們?cè)赾omponents里面新建一個(gè)組件,然后加入以下代碼:
{{ count }}
+
-
methods:{
increment(){
},
decrement(){
},
},
接著新建一個(gè)vuex文件夾,里面新建一個(gè)store.js文件,并加入以下代碼:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// 應(yīng)用初始狀態(tài)const state = {
count: 0,
}
// 創(chuàng)建 store 實(shí)例export default new Vuex.Store({
state,
})
然后我們?cè)诮M件中就可以使用我們的count變量了:
computed:{
count(){
return this.$store.state.count;
},
}
我們定義一個(gè)計(jì)算屬性,返回store中的count變量:
3. 計(jì)算屬性?引入Getter
這里我們可以假想一個(gè)場(chǎng)景,我們的頁面中現(xiàn)在顯示的數(shù)字是0,如果我們的需求是這樣的,頁面中數(shù)字如果小于10,就顯示為00。那我們可以在剛剛的組件中將計(jì)算屬性返回的值修改成這樣:
return this.$store.state.count > 9 ? this.$store.state.count : '0'+this.$store.state.count;
就可以了,但是如果我們有很多組件都使用了這個(gè)count的話,那我們?cè)诿恳粋€(gè)使用這個(gè)變量的地方都需要寫一遍這個(gè)判斷,那為什么不在取數(shù)據(jù)的時(shí)候就把數(shù)據(jù)整理成想要的樣子呢?就和我們組件中的計(jì)算屬性一樣!為了達(dá)到目的,我們修改一下store.js:
import Vue from 'vue'
import Vuex from 'vuex'
import * as getters from './getters' //新增
Vue.use(Vuex)
// 應(yīng)用初始狀態(tài)const state = {
count: 0,
}
// 創(chuàng)建 store 實(shí)例export default new Vuex.Store({
state,
getters //新增})
然后我們新建一個(gè)getters.js文件:
export const countaddzero = state => {
return state.count > 9 ? state.count : '0' + state.count;
}
最后我們改一改組件中的計(jì)算屬性:
return this.$store.getters.countaddzero;
保存之后發(fā)現(xiàn)頁面上的數(shù)字果然變成了00。
4. 試試修改State,引入Mutation
我們的本意是要做一個(gè)點(diǎn)擊按鈕數(shù)字可以增加的一個(gè)小demo,現(xiàn)在把數(shù)據(jù)存到store是完成了。接下來說一下如何修改數(shù)據(jù)。 為了方便查看,我們先修改一下store.js這個(gè)文件:
import Vue from 'vue'
import Vuex from 'vuex'
import * as getters from './getters'
Vue.use(Vuex)
// 應(yīng)用初始狀態(tài)const state = {
count: 0,
}
// 定義所需的 mutations //新增const mutations = { //新增 increment(state, val = 1) { //新增 state.count += val; //新增 }, //新增 decrement(state, val = 1) { //新增 state.count -= val; //新增 } //新增} //新增
// 創(chuàng)建 store 實(shí)例export default new Vuex.Store({
state,
getters,
mutations //新增})
其中的val表示點(diǎn)擊按鈕每次需要增加(減少)多少。 有了mutations我們就可以在組件中對(duì)store里面的state進(jìn)行修改了,我們先處理一下組件中的點(diǎn)擊事件,當(dāng)點(diǎn)擊加或者減按鈕的時(shí)候才去修改store里面的值。我們修改一下組件的methods:
methods:{
increment(){
this.$store.commit('increment',2); //新增 },
decrement(){
this.$store.commit('decrement',2); //新增 },
},
其中的2就是之前提到的每一次增加多少,也就是前文的val。我們約定只能通過commit的方式修改store的變量,為什么說是預(yù)定呢?手賤的我決定試試:
methods:{
increment(){
// this.$store.commit('increment',2); //修改 this.$store.state.count=1000; //新增 },
},
其實(shí)這樣也可以修改store里面的值,但是這樣就不能達(dá)到我們剛開始所說的目的了。 一條重要的原則就是要記住mutation必須是同步函數(shù)。因?yàn)槲覀儾恢朗裁磿r(shí)候回調(diào)函數(shù)實(shí)際上被調(diào)用——實(shí)質(zhì)上任何在回調(diào)函數(shù)中進(jìn)行的狀態(tài)的改變都是不可追蹤的。
5. 異步修改?引入Action
那如果我們就想異步的修改store的值呢?也是有辦法的,這時(shí)候就需要我們的Action出場(chǎng)了: Action 類似于 mutation,不同在于:Action 提交的是 mutation,而不是直接變更狀態(tài)。
Action 可以包含任意異步操作。
我們還是先改改代碼,我們新建一個(gè)actions.js:
export const incrementAsync = ({ commit }, val = 1) => {
setTimeout(() => {
commit('increment', val)
}, 1000)
}
export const decrementAsync = ({ commit }, val = 1) => {
setTimeout(() => {
commit('decrement', val)
}, 1000)
}
這里我們使用setTimeout模擬一下異步執(zhí)行。接著修改我們的組件
異步:
+
-
修改一下methods:
methods:{
increment2(){
this.$store.dispatch('incrementAsync',2);
},
decrement2(){
this.$store.dispatch('decrementAsync',2);
},
},
Action通過store.dispatch方法觸發(fā),乍一眼看上去感覺多此一舉,我們直接分發(fā)mutation豈不更方便?實(shí)際上并非如此,還記得mutation必須同步執(zhí)行這個(gè)限制么?Action 就不受約束!我們可以在 action 內(nèi)部執(zhí)行異步操作。 最后修改一下store.js文件: 在頂部導(dǎo)入actions:import * as actions from './action' 然后在實(shí)例化的時(shí)候加入actions:
// 創(chuàng)建 store 實(shí)例export default new Vuex.Store({
actions, //新增 getters,
state,
mutations
})
這樣就可以實(shí)現(xiàn)異步修改store啦!
6. 不方便維護(hù)?引入Module
由于使用單一狀態(tài)樹,應(yīng)用的所有狀態(tài)會(huì)集中到一個(gè)比較大的對(duì)象。當(dāng)應(yīng)用變得非常復(fù)雜時(shí),store 對(duì)象就有可能變得相當(dāng)臃腫。 為了解決以上問題,Vuex允許我們將store分割成模塊(module)。每個(gè)模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進(jìn)行同樣方式的分割:
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 的狀態(tài)store.state.b // -> moduleB 的狀態(tài)
7. 一點(diǎn)點(diǎn)注意事項(xiàng)
當(dāng)在嚴(yán)格模式中使用 Vuex 時(shí),在屬于 Vuex 的 state 上使用 v-model 會(huì)比較棘手:
假設(shè)這里的 obj 是在計(jì)算屬性中返回的一個(gè)屬于Vuex store的對(duì)象,在用戶輸入時(shí),v-model會(huì)試圖直接修改obj.message。在嚴(yán)格模式中,由于這個(gè)修改不是在 mutation 函數(shù)中執(zhí)行的, 這里會(huì)拋出一個(gè)錯(cuò)誤。 也就是說其實(shí)雙向數(shù)據(jù)綁定和vuex是會(huì)有一點(diǎn)沖突的,不過化解的方法也有: 第一種方法: 給 中綁定 value,然后偵聽input或者change事件,在事件回調(diào)中調(diào)用 action:
也就是不實(shí)用v-model。 第二種方法: 雙向綁定的計(jì)算屬性
computed: {
message: {
get () {
return this.$store.state.obj.message
},
set (value) {
this.$store.commit('updateMessage', value)
}
}
}
總結(jié)
以上是生活随笔為你收集整理的vuex的计算属性_Vuex详细介绍的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python param_Python基
- 下一篇: ios 数字键盘左下角添加按钮_iOS8