1、vuex是幹什麼的?
學習任何東西,必然繞不過去的一個話題,就是我們爲什麼要使用它,它解決了什麼問題?
vuex是基於vue框架的一個狀態管理庫。可以管理複雜應用的數據狀態,比如兄弟組件的通信、多層嵌套的組件的傳值等等。
vuex有這麼幾個核心概念——State、Getter、Mutation、Action、Module。
2、vuex的“hello world”示例
由於數據狀態在多個組件維護的困難性,vuex在維護數據狀態的時候,使用的方法就是對一個“容器”進行維護。這個容器是一個狀態數,用對象的方式來表示。
(1)、store
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
},
decrement (state) {
state.count--
}
}
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
store是vuex的核心對象,它記錄了整個vue應用的數據狀態以及操作數據的方式。
(2)、state
state就是store操作的數據狀態對象。
(3)、mutation
mutation提供了一種簡單易用的同步的方式改變state的狀態。
完整示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuex學習</title>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script src="https://unpkg.com/vuex"></script>
</head>
<body>
<div id="app">
<p>{{ count }}</p>
<p>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</p>
</div>
</body>
<script>
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
},
decrement (state) {
state.count--
}
}
})
new Vue({
el:'#app',
store,
computed:{
count(){
return store.state.count;
}
},
methods:{
increment(){
store.commit('increment')
},
decrement () {
store.commit('decrement')
}
}
})
</script>
</html>
- 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
- 48
- 49
- 50
- 51
- 52
- 53
3、State
是一個單一狀態樹,這個state中維護着整個應用的數據管理的核心對象。
(1)、通過計算屬性獲取state
computed計算屬性是獲取vuex狀態的最簡單的方式。(store.state.count)
state變化,計算屬性會重新獲取state中變化的值。
const Counter = {
template:"<span>{{count}}</span>",
computed:{
count(){
return store.state.count//核心在這裏。
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
(2)、把store的實例注入到每個子組件中
我們的需求,很多情況下要在不同的組件中引用store,我們可以跟組件中直接注入,然後就能在不同的子組件中獲取state。
var app = new Vue({
el:'#app',
store:store//這裏就是注入store的地方
})
- 1
- 2
- 3
- 4
(3)、mapState——獲取多個state數據
由於計算屬性每次基本上只能獲取一個state中的變化。如果獲取多個,就要多個計算屬性來解決。這樣代碼就顯得冗餘。mapState就是用來解決這個問題。
mutations: mapState({
//這是箭頭函數的方式
count: state => state.count,
//這是傳字符串的方式
count: 'count',
//如果要使用this,只能攜程函數的方式。
countAdd(state){
return this.add + state.count
}
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
(4)、獲取多個state的混合寫法(計算屬性+mapState)
mutations:{
count(){
return store.state.count
},
...mapState({ 其他state })
}
- 1
- 2
- 3
- 4
- 5
- 6
4、Getter
如果說state通過計算屬性獲取的數據,我們要經過一定的操作(比如排序),那麼在Getter中我們就可以提供這種操作。使得我們獲取的state達到我們的需求。
它的本質就是對state進行過濾
const store = new Vuex.Store({
state:{
todoList:[{
id: 1,
text: 'do something1',
isDo: true
},{
id: 2,
text: 'do something2',
isDo: false
}]
},
getters:{
doneTodos: funciton(state){
return state.todoList.map(item=>item.isDo == true)
}
}
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
(1)、獲取getter——store.getters
是getter對外暴露的數據讀取方式
如: store.getters.doneTodos獲取了過濾後的state
(2)、Getter 也可以接受其他 getter 作爲第二個參數
getters: {
// ...
doneTodosCount: (state, getters) => {
return getters.doneTodos.length
}
}
store.getters.doneTodosCount // -> 1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
(3)、mapGetters——獲取多個getters的方式
使用方式和mapState差不多
5、Mutation
這是vuex提供的唯一更改store的屬性。
(1)、定義一個帶有Mutation的store
const store = new Vuex.Store({
state:{
count: 0
},
mutations:{
increment(state){
state.count++
}
}
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
觸發方式:store.commit(‘increment’)
通過這樣的方式,讓state中的數據改變。
(2)、提交載荷
意思就是在commit的時候,傳入額外的參數
store.commit('increment',{
num: 10
})
- 1
- 2
- 3
也可以是這樣:
store.commit({
type: 'increment',
num: 10
})
- 1
- 2
- 3
- 4
(3)、應該遵守的相應規則
第一、提前在你的 store 中初始化好所有所需屬性。
第二、當需要在對象上添加新屬性時,你應該:
Vue.set(obj, ‘newProp’, 123)
state.obj = { …state.obj, newProp: 123 }
//這兩種方式都是把對象obj更新。
6、Action
這個屬性的作用類似於Mutation,但是它提交的是mutation,而不是變更狀態。並且action可以包含任何異步狀態。
(1)、註冊action
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
actions中的函數的參數是context,這個context有commit、getter、state等屬性。
(2)、分發 Action
定義好了Action,就需要在JavaScript中觸發這個Action。我們通過dispatch來觸發。
store.dispatch('increment')
- 1
// 以載荷形式分發
store.dispatch('incrementAsync', {
amount: 10
})
// 以對象形式分發
store.dispatch({
type: 'incrementAsync',
amount: 10
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
(3)、異步操作
actions: {
incrementAsync ({ commit }) {
setTimeout(() => {
commit('increment')
}, 1000)
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
(4)、在組件中分發 Action
this.$store.dispatch('xxx') //分發 action
- 1
7、module模塊組
隨着項目越來越大,我們定義的狀態會越來越多,這個時候,我們要對我們的狀態進行模塊劃分。而module就是來幹這樣的事情的。
第一步、定義模塊。
const moduleA = {
state:{},
getters:{
},
mutations:{},
actions:{}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
第二步、改變 Vuex.Stroe 的寫法。
store = new Vuex.Store({
modules:{ a: moduleA }
})
- 1
- 2
- 3
第三步、在頁面中的使用方式
<div>{{$store.state.a.count}}</div>
- 1
如果想在頁面中使用computed直接獲取,可以這樣寫:
computed:{
count(){
return this.$store.state.a.count;
}
}
- 1
- 2
- 3
- 4
- 5