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