項目使用 Flux 模式來實現的 SPA,Vuex 是不可繞過的
Flux 是一種架構思想,專門解決軟件的結構問題。它跟MVC 架構是同一類東西,但是更加簡單和清晰。
from http://www.ruanyifeng.com/blog/2016/01/flux.html
網上有一本電子書:《Vuex Concepts: The Flux Application Architecture for Vue.js》對 Vuex 是 Flux 實現介紹的非常深入淺出,可以搜索到下載地址:
https://leanpub.com/vuex
官方文檔是必要的手冊補充:
https://vuex.vuejs.org/en/
(本文以下內容為目前自身項目的階段性設計,所以不建議閱讀)
步驟一:
通過異步請求的方式,從后端獲取到頁面需要的數據,將獲取到的數據保存到 Vuex 中
建立 store.js 作為 Vuex 的數據存放對象,使用 axios 對數據進行異步加載:
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
import VueAxios from 'vue-axios'
Vue.use(Vuex, VueAxios, axios)
export default new Vuex.Store({
state: {
courses: {} // 如果需要深度響應,必須寫清楚對象,形如:courses: {a:''}
},
mutations: {
setCourses (state, res) {
state.courses = res
}
},
actions: {
getCourses (store) {
axios.get('/getCourses').then((response) => {
store.commit('setCourses', response.data)
})
}
}
})
在任何頁面中(一般在 layout 中)調用基于 Vue 對象的這段代碼,就可以對 Vuex 中的數據進行初始化:
this.$store.dispatch('getCourses')
步驟二:
子模塊響應 Vuex 中的數據變化,調用 Vuex 的 getters 接口獲取最新加載的數據,并渲染頁面
先將 Vuex 中的數據對象映射到子模塊中
computed: mapState([
'courses'
]),
然后對這個數據對象建立 watch 監控 courses 的數據變化
watch:{
courses:function(){
this.courseName = this.$store.getters.getCourseById(this.courseId).courseName;
}
},
上面的例子里面使用了 Vuex 的 getters 接口,方便數據獲取的封裝處理,getters 定義在 store.js 中:
getters: {
getCourseById: (state, getters) => (id) => {
return state.courses.find(course => course.course_id == id)
}
}
踩坑:
-
子模塊中如果有同名的數據對象,會讓 Vuex 的響應失敗,比如前面的例子中,如果有這樣的代碼在預定義中:
data () { return { courses: '' } },
getters mutations actions 三者的差異:
- getters:第一個參數是 state,可以拿到數據,getters會暴露給 store.getters 進行直接調用
- mutations:第一個參數是 state,相當于 setters,可以對 state 進行直接的寫入操作
- actions:參數中沒有 state,所以不能直接的操作 state 的值,但是可以調用 getters 和 mutations 來進行對數據變化的控制
深度響應問題
有時候因為 state 的結構會比較復雜,而默認用 state.test.a = value 這樣的方式是無法響應的,所以需要用:
mutations: {
setTest (state, value) {
Vue.set(state.test, 'a', value)
},
},
mapState 和 mapActions
Vue 提供了 mapState 和 mapActions 兩個方法,可以將 Vuex 里面的 state 和 actions 映射到 components 里面,于是可以在 components 中這么使用:
this.stateName
this.actionName()
PS:mapState 必須在 computed 屬性中使用,mapActions 必須在 methods 方法中使用