之前看vuex的教程,看了好幾遍,還是沒有能夠理解到底是怎麼用,覺得自己有點笨。
昨天看vue教程 規模化-簡單狀態管理起步使用,看到一句話後(見下面紅字),頓然醒悟
組件不允許直接修改屬於 store 實例的 state,而應執行 action 來分發 (dispatch) 事件通知 store 去改變
帶着這句話,再次看vuex教程
先放store文件中,index.js代碼
const store = new Vuex.Store({
state: {
count: 0,
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos: state => {
console.log("test")
return state.todos.filter(todo => todo.done)
},
doneTodosCount: (state, getters) => {
console.log("test2")
return state.todos.filter(todo => todo.done)
}
},
mutations: {
increment (state) {
state.count++
},
[SOME_MUTATION] (state, params) {
let param = {...params}
console.log(param.title)
}
}
})
1.State
存儲各種變量
看,index.js代碼
state: {
count: 0,
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
再看,test.vue代碼
記住使用state裏面的屬性,要引用 mapState(見下)
// 在單獨構建的版本中輔助函數爲 Vuex.mapState
import { mapState } from 'vuex'
記住!記住!mapState中簡寫的屬性名和state中一樣
// 代碼片段,後期會附上整段代碼
computed: {
...mapState([
// 映射 this.count 爲 store.state.count
'count'
])
},
mounted(){
console.log(this.count) // 對應mapState中的count
}
2.Getter
一開始的組件代碼中有此屬性緩存
computed: {
doneTodosCount () {
return this.$store.state.todos.filter(todo => todo.done).length
}
}
假設這個屬性值需要用到多個組件,你就得在每個組件中複製同樣的代碼,或者抽取到一個共享函數然後在多處導入它。噹噹噹,你就需要Getter來管理咯
看,store文件夾中index.js
getters: {
doneTodos: state => {
console.log("test")
return state.todos.filter(todo => todo.done)
},
doneTodosCount: (state, getters) => {
console.log("test2")
return state.todos.filter(todo => todo.done)
}
},
再看,test.vue文件中
記住使用getter裏面的屬性,要引用 mapGetters(見下)
import { mapGetters } from 'vuex';
記住!記住!mapGetters中簡寫的屬性名和getters中一樣
computed: {
...mapGetters([
'doneTodosCount' //對應getters裏面的方法
])
},
3.Mutation
更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation。(就是你要更改state中的值,需要通過mutation改)
看,store文件夾中index.js
mutations: {
increment (state) { // increment爲函數名
state.count++
}
}
類似於method中定義事件
再看,test.vue文件中
記住使用mutation裏面的方法,要引用 mapMutations(見下)
import { mapMutations } from 'vuex';
那它的引用,放在哪裏呢?就放在methods,想象下mutation裏是不是就是調用方法去改變state中內容
methods:{
...mapMutations([
'increment'
]),
使用常量替代 Mutation 事件類型(去官網看)
4.Action
Action 類似於 mutation,不同在於:
- Action 提交的是 mutation,而不是直接變更狀態。
- Action 可以包含任意異步操作。
當你mutation中的某個幾個方法需要同步,可以使用async/await
看,store文件夾中index.js
actions: {
incrementTest ({ commit }) { // 普通調用
console.log( "action" )
commit('increment') // increment 對應爲mutation中調用同名方法
},
async actionA ({ commit }) { // 帶有異步/同步的寫法
commit('increment', await getTest()) // getTest爲外部API函數
console.log("actionA")
},
async actionB ({ dispatch, commit }) {
await dispatch('actionA') // 等待 actionA 完成
commit('increment', await getOtherData()) // getOtherData爲外部API函數
}
}
再看,test.vue
記住actions使用裏面的方法,要引用 mapActions(見下)
import { mapActions } from 'vuex';
methods:{
...mapActions([
'incrementTest', // 將 `this.increment()` 映射爲 `this.$store.dispatch('increment')`
'actionA',
'actionB'
])
}
test.vue整合的全部代碼
<template>
<div class="Test">
{{ count }}
{{doneTodosCount}}
</div>
</template>
<script>
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex';
export default {
name: 'Test',
data () {
return {
}
},
computed: {
...mapState([
// 映射 this.count 爲 store.state.count
'count'
]),
...mapGetters([
'doneTodosCount'
// ...
]),
},
mounted(){
console.log(this.count)
this.SOME_MUTATION({title:"testig"})
this.incrementTest()
},
methods:{
...mapMutations([
'SOME_MUTATION'
]),
...mapActions([
'incrementTest', // 將 `this.increment()` 映射爲 `this.$store.dispatch('increment')`
'actionA',
'actionB'
])
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
index.js代碼
import Vue from 'vue'
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types.js'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0,
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos: state => {
console.log("test")
return state.todos.filter(todo => todo.done)
},
doneTodosCount: (state, getters) => {
console.log("test2")
return state.todos.filter(todo => todo.done)
}
},
mutations: {
increment (state) {
state.count++;
console.log(state.count)
},
[SOME_MUTATION] (state, params) {
let param = {...params}
console.log(param.title)
}
},
actions: {
incrementTest ({ commit }) {
console.log( "action" )
commit('increment')
},
async actionA ({ commit }) {
commit('increment', await getTest())
console.log("actionA")
},
async actionB ({ dispatch, commit }) {
await dispatch('actionA') // 等待 actionA 完成
commit('increment', await getOtherData())
}
}
})
// store.dispatch('incrementTest')
// console.log( JSON.stringify(store.getters.doneTodos))
// store.dispatch('increment')
// console.log(store.state.count) // -> 1
export default store
main.js
import store from './store' // 導入vuex文件
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>',
store // 要引用
})