場景是這樣的:
這樣一個操作, 需要同時依賴很多個 Model, 因此這些程式碼不會寫在某一個 Model 裡邊.
有可能是例如 Backbone, 寫在 ViewController 裡邊... 但是這樣程式碼復用不好, 而且 View 會變亂.
我目前採取的方案是用單獨一個文件去收集大部分的 Model 操作, 不過問題是, 這個文件會不斷變大變亂.
所以這樣的問題該如何解決?
延伸的問題是, 怎麼整理這部分程式碼?
例如我用 React 的 Flux 方案, 盡量將流程理清楚, 就發現這部分程式碼不知道放在哪裡合適..
Flux 將使用者操作轉換為 Actions, Store 透過 Dispatcher 監聽這些 Actions,
一個 Actions 對應多個 Store 的時候... 問題就來了:
我該用多個 Actions 分別對應 Store, 還是一個 Action 由多個 Store 來監聽?
曾经蜡笔没有小新2017-05-16 17:08:22
用戶點擊按鈕本質上跟用戶透過URL訪問一樣,都是一種‘輸入’,所以問題和處理機制都是一樣的:在view層代碼裡監聽‘輸入’,處理一些view層(比如按鈕組件的toggle、URL的矯正)內部的狀態變化,生成/提取出純粹的、抽象層級更高的(跟view組件或URL細節無關)數據/訊息,用某種事件機制廣播出去,之後就跟自己沒關係了,接下來如果有controller層的話,在這部分的程式碼裡監聽這些事件,調用相應model物件的方法(其中可能封裝了model物件自己之間的依賴關係和調用,但這裡的一對多複雜性不會暴露到外面去),同時也監聽某些model物件的狀態變化,呼叫對應view物件的方法(或是重新渲染Virtual DOM)。所有東西綁定完成。
像我平常用NervJS(model) + DermJS(view)+ URLKit(route) 這樣的搭配,NervJS和DermJS物件都有自帶的事件方法,此外也可以在view/model物件初始化時傳入統一的bus事件對象。
你寫一個UI component的時候當然不會希望它依賴特定的model,寫一個model組件的時候,也不會希望它依賴特定UI,所以一對多之類的綁定是在另一個地方(專門的業務邏輯程式碼)完成的,view物件和model物件不需要也不應該知道對方有幾個、是哪些,所以也不可能『多個Actions 分別對應Store』。
至於『單獨一個檔案』、『不斷變大變亂』的問題,跟設定路由的檔案也是一回事,可以參考相關經驗。
曾经蜡笔没有小新2017-05-16 17:08:22
flux裡,如果需要一個動作對應多個Store,其實也是很好解決的。
在Store裡面register回呼的時候,可以都對這個動作進行相應就可以了,還可以透過waitFor
來改變對應的順序。
如果擔心程式碼變亂的話,可以再單獨寫一個constants
文件,定義好觸發的事件名稱就可以了。
舉例:
點選一個按鈕,觸發send
事件,会更新两个Store
分别是StoreA
和StoreB
。可以写一个constants.js
,先定義事件名稱:
constants:
module.exports = {
"ActionTypes": {
"SEND": "SEND"
}
};
然後在兩個Store
裡面分別註冊回調:
StoreA:
var AppDispatcher = require('path/to/disp'),
constants = require('path/to/constants');
StoreA.dispatchToken = AppDispatcher.register(function(payload) {
var action = payload.action;
if (action.type === constants.ActionTypes.SEND) {
// callback A
};
});
StoreB:
var AppDispatcher = require('path/to/disp'),
constants = require('path/to/constants');
StoreB.dispatchToken = AppDispatcher.register(function(payload) {
var action = payload.action;
if (action.type === constants.ActionTypes.SEND) {
// callback B
};
});
在觸發點擊事件的時候,在Action
中触发Disp
的这个事件,就会顺序执行在StoreA
和StoreB
中註冊的回調了:)
曾经蜡笔没有小新2017-05-16 17:08:22
如果沒看過,或是看過但忘了,這是一篇值得讀的文章:
Patterns For Large-Scale JavaScript Application Architecture
簡單而言,你需要有些「約定俗成」的東西,讓view和model無需相互依賴(不管是1:1的依賴,還是1:N的依賴)。
用簡單的event和observer pattern也可以,如果業務邏輯很複雜,用mediator完成模組間的通訊和同步。
PS:理想的情況是,你的每個模組都只知道自己(觸發什麼事件,聆聽什麼事件),除此之外都不管,更不會知道對方的instance,或者mediator的instance。