1飘痛、思想:基于響應(yīng)式的原理:所有的狀態(tài)的變更都是因?yàn)閿?shù)據(jù)的變化引起的
汽绢。
2、背景:在傳統(tǒng)的vue應(yīng)用中卷玉,我們可能定義許多component
,而每個(gè)component可能是這樣的:
var component_library_title = {
props: ['text'],
data:{
a:'',
b:''
},
template: '<div>{{text}}</div>'
};
這樣哨颂,在不用的component中,就會出現(xiàn)屬于不用vue的組件管理的data數(shù)據(jù)相种,這樣威恼,如果在父子component或者兄弟component中進(jìn)行數(shù)據(jù)傳遞的時(shí)候,會比較混亂寝并。
3箫措、解決:將所有的data交給vuex管理。
- 如何獲取數(shù)據(jù):
因?yàn)樵趘ue的computed
鉤子中衬潦,其中的方法會在管理的數(shù)據(jù)源發(fā)生變更的時(shí)候蒂破,主動調(diào)用并更新數(shù)據(jù),所以這樣正好别渔,我們可以知道vuex管理的store發(fā)生變更的時(shí)候,數(shù)據(jù)如何變化。
- 如何更改數(shù)據(jù):
通過commit或者dispatch去發(fā)送事件更改數(shù)據(jù)源哎媚,而不建議直接調(diào)用類似store.data.a
去更改數(shù)據(jù)喇伯。
核心概念
State
單一狀態(tài)樹:一個(gè)應(yīng)用只對應(yīng)一個(gè)狀態(tài)樹逝段,且這種思想和組件化并不沖突士骤!
1、將State注冊到所有的子組件中
const app = new Vue({
el: '#app',
// 把 store 對象提供給 “store” 選項(xiàng)衬鱼,這可以把 store 的實(shí)例注入所有的子組件
store,
components: { Counter },
template: `
<div class="app">
<counter></counter>
</div>
`
})
如果想直接訪問store實(shí)例中的屬性买喧,可以這樣:this.$store.state.屬性
進(jìn)行訪問捻悯。
2、使用mapState
3淤毛、在子component中使用store中的state
你需要在子component
中的computed
鉤子中創(chuàng)建方法
computed: {
count () {
return this.$store.state.count
}
}
然后在需要使用的地方今缚,直接{{count}}
就可以了。
Getters
其實(shí)是一種規(guī)范吧:
本來我們在子component中就能夠通過如上的方法獲取store的state的屬性低淡,但是姓言,假設(shè)我們希望對直接定義在store中的屬性進(jìn)行一些操作(這里官方網(wǎng)站說的是一些filter操作等),我們希望不要再修改
mapState
或者直接通過return this.$store.state.count
來進(jìn)行數(shù)據(jù)的獲取或者修改蔗蹋。于是就使用
getter
進(jìn)行數(shù)據(jù)的操作并裝換何荚。注意到,我們在修改一個(gè)的時(shí)候猪杭,可能需要同時(shí)和其他的store中的state下面的數(shù)據(jù)進(jìn)行以前操作餐塘,這就意味著,我們需要拿到
state
這個(gè)對象皂吮。而的確是這樣的戒傻,getters中允許我們在定義的方法中帶有
state
參數(shù)
1、定義
getters: {
count(state){
return state.count + 1;
},
}
2涮较、使用
computed: {
getMessage(){
return this.$store.state.count;
},
}
你需要在子component中的computed
鉤子中定義方法稠鼻,這樣就能直接使用了。
Mutations
我們會返現(xiàn)狂票,在Vuex
中候齿,只有Getter
的定義,而沒有類似于Setter
的定義.
其實(shí)闺属,這里的Mutations
就是Setter
的實(shí)現(xiàn).
雖然我們能夠通過this.$store.state.屬性
獲取到某個(gè)屬性慌盯,并進(jìn)行修改,但是掂器,vuex強(qiáng)烈建議我們不要這樣做亚皂。
1、直接修改在$store.state
中的值
我們直接在子component中定義了一個(gè)方法国瓮,用來直接$store.state
中的值灭必。
- html中
template: '<div>{{getMessage}}并且:{{getMessage1}}' +'<button @click="changeMessage">修改</button>' +'</div>',
- js中
methods: {
changeMessage(){
console.log(this.$store.state.count);
this.$store.state.count = 100;
}
}
我們發(fā)現(xiàn)狞谱,在調(diào)用changeMessage
后,this.$store.state.count
變成了100禁漓。
說明我們本身是能夠直接調(diào)用this.$store.state.count
進(jìn)行state中值得修改的跟衅。
Note:但是,Vuex建議我們不要這樣做播歼,如果需要修改
this.$store.state
中的值伶跷,建議在store中的Mutations
鉤子中進(jìn)行方法的定義來完成。
2秘狞、使用Mutations
mutations: {
increment (state) {
// 變更狀態(tài)
state.count++
}
}
注意在定義方法的時(shí)候叭莫,可以攜帶state
參數(shù)。
3烁试、觸發(fā)方法
方法一:使用方法名稱
在本component中
store.commit('方法名稱');
在子component中
this.$store.commit('方法名稱');
方法二:使用對象
store.commit({
type:'方法名稱'雇初,
...
});
4、使用常量定義mutations中的方法名
mutations: {
[INCREMENT](state){
state.count++;
},
[DECREMENT](state){
state.count--;
},
},
這樣廓潜,就會比較方便的進(jìn)行管理了抵皱。
Actions
顧名思義,這也是一個(gè)可以改變state中屬性的方法集辩蛋。但是mutations中不是已經(jīng)提供了可用的方法集合了嘛呻畸?!
但是悼院,如果你在Mutations中寫就的方法集合中某個(gè)方法是異步的伤为,那么我們不建議將異步方法寫在Mutations
中(雖然的確是可以的)。
那么据途,我們需要將這些方法寫在Actions
中绞愚。
1、寫法
actions: { asyncIncrement(context){ console.log('asyncIncrement'); context.commit('INCREMENT'); }}
2颖医、調(diào)用
這里稱之為“分發(fā)”位衩。
asyncIncrement(){
store.dispatch({
type: 'asyncIncrement',
amount: 4,
});
}
3、在模塊中分發(fā)消息
changeMessageAsync(){
console.log('異步修改');
this.$store.dispatch('asyncIncrement')
}
這樣熔萧,直接使用this.$store.dispatch('asyncIncrement')
進(jìn)行分發(fā)糖驴。
表單操作
傳統(tǒng)方法(不按照Vuex的思路去管理數(shù)據(jù))
Vuex的思維方式:我們需要將數(shù)據(jù)統(tǒng)一管理,使用computed
時(shí)刻觀察數(shù)據(jù)的變化佛致,并通過commit
或者dispatch
的方式改變數(shù)據(jù)贮缕。
那么我們只需要使用v-model
就能方便簡單的實(shí)現(xiàn)了。
但是一旦我們在某處使用了vuex俺榆,并且我們希望在任何地方也使用vuex的思維進(jìn)行數(shù)據(jù)的管理感昼。
那么問題就來了。
- 問題來了:
<input type="text" v-model="bookSerialNumber"/>
computed:{ bookSerialNumber(){
return this.$store.state.book.serialNumber;
},
},
我們只能通過計(jì)算屬性(computed)計(jì)算出當(dāng)前this.$store.state.book.serialNumber
的值,而無法實(shí)現(xiàn)該值的修改罐脊。
除非我們在方法
bookSerialNumber
中通過直接改變this.$store.state.book.serialNumber
的值定嗓,但是這樣是明顯不符合vuex方法論的蜕琴。
vuex的解決
<input type="text" @input='bookNameInputChange' :value='bookName'/>
為你的表單中的某一項(xiàng):
- 使用
:value
單向綁定某個(gè)在computed
中實(shí)現(xiàn)的計(jì)算屬性; - 使用
@input
監(jiān)聽控件的輸入的變化宵溅,這樣就實(shí)現(xiàn)了setter的方法奸绷,我們通過在mutations
中定義的屬性對屬性進(jìn)行控制,假設(shè)這個(gè)改變的過程是異步的层玲,你需要在actions
中定義屬性,并通過dispatch
進(jìn)行事件的分發(fā)反症。
vue的方法論
- 通過
state
設(shè)置元(原)數(shù)據(jù)辛块; - 通過
getters
設(shè)置訪問元數(shù)據(jù)的屬性(function),一般這里的屬性是邏輯是直接獲取原屬性铅碍,不再做其他的操作润绵; - 通過
mutations
設(shè)置改變元數(shù)據(jù)的屬性(function),并且約定這里的方法都是同步適宜的胞谈。 - 通過
actions
設(shè)置改變元數(shù)據(jù)的異步方法尘盼。