第12屆鐵人賽Day 23 Rails專案開發 - Vuex狀態管理 (1)
昨天我把一張自己開給自己的票:拖拉ticket
解決了!
接著換下一張票、同時也就是今天的鐵人賽主題:改寫成Vuex來管理狀態~
在鐵人賽第13天的時候曾經聊到Vuex狀態管理,當我們的專案發展規模越來越大,元件越來越多,如何讓資料在跨元件之間溝通就是一件非常重要的事情。
(如果一直讓子元件用$emit
傳給父元件、父元件再用props
傳給其他子元件,這樣來來回回也太辛苦了吧~~~)
這時候,我們會使用Veux去產生一個用來管理網站全域的Shared State
(共享狀態)的實體,而這個實體我們通常會把它取名叫做store
(英文意思為倉庫)。
參考官網影片介紹的Vuex架構,今天我們就來把原本元件裡的data
(如下圖左側)拉出來到store
(下圖右側)獨立管理吧!
Step0. 安裝並引入Vuex
首先在Rails 6專案裡利用指令yarn add vuex
安裝,這在第13天已經進行過了~
yarn add vuex
//略
...
success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ vuex@3.5.1
info All dependencies
└─ vuex@3.5.1
✨ Done in 3.30s.
Step1. new出Vuex的實體
在今天的任務,要從Vue元件裡的data
拉出來、挪到store
獨立管理的State
叫做columns
,先跟之前的元件寫法一樣,預設是一個空陣列。
如果元件想要使用State
的話,是使用Getters
屬性取值(state
為Getter
的第一個參數)
參考官網教學影片的Store
流程圖:
我們寫在stores/column.js的路徑下的Vuex元件長得像這樣:
import Vue from 'vue/dist/vue.esm'
import Vuex from 'vuex'
Vue.use(Vuex)
// 定義一個新的 Vue Store
export default new Vuex.Store({
state: {
// 預設空陣列
columns: []
},
getters:{
columns: state => state.columns
},
mutations: {
// 任何更改columns的值的行為都必須透過mutation
UPDATE_COLUMNS(state, columns){
state.columns = columns;
}
},
actons: {
}
});
Step2. application.js 引入 Vuex
的store
剛剛寫完熱騰騰的column.js
趕快引入到原本的component:
import store from 'stores/column'
並且在new Vue裡面應該再加上store
(import後就可以使用)
import Vue from "vue/dist/vue.esm";
import Column from "components/kanban/column"
import Rails from '@rails/ujs'
import Draggable from 'vuedraggable';
import store from 'stores/column';
document.addEventListener("turbolinks:load", () => {
let el = document.querySelector("#column");
if (el){
new Vue({
el,
store, // import後就可以使用store
data: {
kanban_id: el.dataset.kanbanid,
// columns: [] => 此時已經把column資料挪到Vuex裡了,原本的Vue可以把此段移除
},
components: { Column, Draggable },
methods: {
// 略
},
beforeMount(){
// 略
}
});
}
})
而Veux最大的重點是:之後有任何想要進行修改State
的動作,都必須要透過Actions
提交commit給Mutations
。
(至於Actions
在今天的需求裡該怎麼撰寫呢?稍安勿躁,請繼續往下看~)
Step3. 思考:Column的Actions
之前在講解column
元件時,有帶到生命週期的beforeMount()
,在這個lifecycle hook會在畫面渲染至瀏覽器前的階段,把打API的結果更新至column
陣列。
所以你應該猜到了~我們接下來要把以下這段beforeMount
改寫進Actions
:
beforeMount(){
Rails.ajax({
url: `/kanbans/${this.kanban_id}/columns.json`,
type: 'GET',
dataType: 'json',
success: result => {
this.columns = result;
},
error: error => {
console.log(error);
}
});
}
以上是Vuex作用的流程圖,為了透過Actions
提交commit給Mutations
,
我們把上一段搬移進去Vuex.Store
的columns.js,
寫一個名為fetchColumn()
的function,參數有commit
,以及打後端API路徑需要知道的kanbanid
actions: {
fetchColumn({ commit }, kanbanid){
Rails.ajax({
url: `/kanbans/${kanban_id}/columns.json`,
///API路徑:kanbans/2/columns.json
type: 'GET',
dataType: 'json',
success: result => {
commit("UPDATE_COLUMNS", result);
//console.log(result);
},
error: error => {
// console.log(error);
}
});
}
}
以下是專案的程式碼截圖:
左邊代表原本的Vue
寫法,右邊是改寫為Vuex
主要把beforeMounted的code移動到actions
來,再透過commit
給mutation
把資料寫回去:
是不是跟Vuex官網的架構有87%像啊?(所以說~~官網要認真看!)
改寫完Vuex
之後,點擊Kanban
,可以順利載入Column以及所屬的ticket
。
於是我們又可以把這一張票:改寫成vuex管理狀態
移到DONE
了 :)
小提醒:
- 寫
javascript
可以善用console log
把接到的資料印出來看看,加快開發速率喔! Vue devtool
也要隨時開著,看有沒有紅字錯誤或警告訊息~
Ref: