一、簡介
Vuex是服務於Vue.js應用程式的狀態管理模式。
vue狀態管理分為三部分
vuex的設計思想:在多個元件共用狀態時,將該共用狀態抽離出來以一個全域性單例模式管理。通過定義和隔離狀態管理中的各種概念,並通過強制規則維持檢視和狀態間的獨立性,讓程式碼變得更結構化且易維護。
二、安裝
npm安裝
npm install vuex --save
在模組化的打包系統中,通過Vue.use()安裝vuex
(當通過全域性script標籤參照Vuex時,不需要使用Vue.use()安裝)
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
三、Store與State
每一個Vuex應用的核心就是store倉庫,store是一個容器,包含應用中大部分的state。
Vuex與單純的全域性物件的區別:
1、Vuex狀態儲存是響應式的,當vue元件從store中讀取state時,若state發生變化,則相應的元件也會相應地得到高效更新。
2、不能直接改變store中的state,改變的唯一途徑就是commit mutation。可以更方便跟蹤每一個狀態的變化。
使用new Vuex.Store()建立store
import Vue from 'vue'
import Vuex from 'vuex'
/*安裝Vuex*/
Vue.use(Vuex)
//建立一個store範例
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
}
})
//建立一個元件範例,讀取state,修改state
const Counter = {
template: `<div>
<div class="btn" @click='add'>增加</div>
{{count}}</div>`,
computed: {
//將state定義為計算屬性
count() {
// return store.state.count
//在根範例vm中註冊store以後,所有子元件都能通過this.$store存取到state
return this.$store.state.count
}
},
methods: {
add() {
//修改state必須提交一個commit
// store.commit('increment')
//在根範例vm中註冊store以後,所有子元件都能通過this.$store存取到state
this.$store.commit('increment')
}
}
}
//建立一個vue範例,提供一個建立好的store
let vm = new Vue({
el: '#app',
store, //把store物件提供給‘store’選項,可以把store的範例注入所有子元件中
components: {
Counter
}
})
mapState獲取多個狀態
當一個元件需要獲取多個狀態時,將這些狀態都宣告為計算屬性會有些重複和冗餘,可使用mapState輔助函數幫助我們生成計算屬性。
//引入mapState
//import {mapState} from 'vuex'
const mapState = Vuex.mapState
const store = new Vuex.Store({
state: {
count: 0,
isLogin: true,
user: {
username: 'Liane',
id: '1',
gender: 'female'
}
},
mutations: {
increment(state) {
state.count++
}
}
})
const Counter = {
template: `<div>
<div class="btn" @click='add'>增加</div>
<div>{{count}}</div>
<div>{{user.username}}</div>
<div>{{user.id}}</div>
</div>`,
//使用mapState()輔助函數
computed: mapState({
// count() {
// return this.$store.state.count
// }
//count可簡化如下
count: state => state.count,
isLogin: state => state.isLogin,
user: state => state.user
}),
methods: {
add() {
this.$store.commit('increment')
}
}
}
let vm = new Vue({
el: '#app',
store,
components: {
Counter
}
})
當對映的計算屬性名稱與state的子節點名稱相同時,也可以給mapState()傳遞一個字串陣列
computed: mapState([
'count',
'isLogin',
'user'
])
通常我們使用擴充套件運運算元將需要用到的state通過mapState與元件的計算屬性混合
computed:{
...mapState([
'count',
'isLogin',
'user'
])
}
四、Getter
當我們需要store中的某些state派生出一些狀態時,可以使用Getter,getter就像是store中的計算屬性一樣,會根據它的依賴被快取起來,依賴一旦發生改變,就會重新計算。
//定義一個store儲存代辦事項的狀態
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: 'study', done: true },
{ id: 2, text: 'exercise', done: true },
{ id: 3, text: 'painting', done: false }
]
},
getters: {
//得到已完成的事項
doneTodos: state => {
return state.todos.filter(todo => todo.done)
},
//得到已完成的事件個數
doneTodosCount: (state, getters) => {
return getters.doneTodos.length
}
}
})
const Counter = {
template: `<div>
<span>已完成{{doneTodosCount}}件代辦事項</span>
<ul>
<li v-for="item in doneTodos">
{{item.text}}
</li>
</ul>
</div>`,
computed: {
doneTodos() {
return this.$store.getters.doneTodos
},
doneTodosCount() {
return this.$store.getters.doneTodosCount
}
}
}
let vm = new Vue({
el: '#app',
store,
components: {
Counter
}
})
mapGetter輔助函數
computed: {
...mapGetter([
'doneTodos',
'doneTodosCount'
])
}
若想將getter屬性另取名字,可使用物件形式
computed:{
...mapGetter({
doneCount: 'doneTodosCount'
})
}
五、Mutations
更改store中屬性的唯一方法就是commit一個mutation。
vuex中的mutation類似事件,每個mutation都有一個字串的事件型別(type)和一個回撥函數(handler)
const mapState = Vuex.mapState
const store = new Vuex.Store({
state: {
isLogin: false,
user: {}
},
mutations: {
setLogin(state, val) {
state.isLogin = val
},
setUser(state, val) {
state.user = val
}
}
})
const Counter = {
data() {
return {
username: ''
}
},
template:
`<div>
<div v-if='isLogin'>
{{user.username}}已登入
<a @click="signOut" href="javascript:;">退出登入</a>
</div>
<div v-else>
<input v-model="username" placeholder="輸入使用者名稱">
<div class="btn" @click="submit">登入</div>
</div>
</div>`,
computed: {
...mapState(['isLogin', 'user'])
},
methods: {
submit() {
if (this.username) {
this.$store.commit('setLogin', true)
this.$store.commit('setUser', {
id: 1,
username: this.username
})
}
},
signOut() {
this.$store.commit('setLogin', false)
this.$store.commit('setUser', {})
}
}
}
let vm = new Vue({
el: '#app',
store,
components: {
Counter
}
})
六、Actions
Action類似於mutation,區別:
1、Action提交的是mutation,而不是直接變更狀態。
2、Action可以包含任意非同步操作