摘要:中發(fā)布訂閱模式使用場景怎么能將設計模式應用到我們的項目中以前一直在思考這個問題。兩個模塊在事件系統(tǒng)唯一的聯(lián)系就是事先定義好事件的。
react 中發(fā)布訂閱模式使用 場景
怎么能將設計模式應用到我們的 React 項目中?以前一直在思考這個問題。
場景一模塊 A 模塊 B 需要用到同一個數(shù)據(jù) data,A 和 B 都會修改這份數(shù)據(jù),且這兩個模塊會同時存在;這時我們如何做到數(shù)據(jù)公用與各個模塊的更新?
方案一:
將這份數(shù)據(jù)作為公共的數(shù)據(jù) data,A B 模塊同時使用并更改這份數(shù)據(jù)這一份數(shù)據(jù)。若使用 redux 代碼可能是這樣:
// store const store = { common: { data: [] }, A: {}, B: {}, }; // reducer function commonReducer(state = { data: [] }, action) { switch (action.type) { case "common_setData": { return { ...state, data: action.data, }; } default: return state; } } // connect const actionCreator = () => {}; connect(({ A, common }) => ({ ...A, data: common.data }))(A); connect(({ B, common }) => ({ ...A, data: common.data }))(B); // change // A B change調用方法; this.props.dispatch({ type: "common_setData", data: [1, 2], });
好的,第一種場景可以使用 redux 完美解決
方案二:待補充
場景二A 模塊使用了 data1, B 模塊使用了 data2;A B 模塊可以修改對應的 data;這兩份 data 結構上不同,但是存在業(yè)務上的聯(lián)系: 當 data1 更新后需要 data2 更新;data2 更新同樣需要 data1 同步;對應后端的兩個不同的 API。
我們整理一下
A B 使用兩份存在聯(lián)系的 data
其中一個更新需要另一個更新
兩份 data 對應不同的 API 接口
A B 對應兩個不同的 tab 且可能同時存在
方案一當其中一個數(shù)據(jù)因操作發(fā)生更新時,判斷另一個模塊是否存在 如果存在則調用他的數(shù)據(jù)更新邏輯;
如果你使用了 redux,可能方便一點:
// reducerA // 省略B function reducerA(state = { data: [] }, action) { switch(action.type) { case "A_setDataA": { return { ...state, data: action.data } } default: return state } } // 假設使用了thunk中間件 const queryA = () => async (dispatch, getState) => { const dataA = await API.queryA() dispatch({ type: "A_setDataA" data: dataA }) } // page class B extends React.Component { handleUpdateData = () => { // 如果 A模塊存在 const { isAExistFlag, dispatch, queryA, queryB } = props dispatch(queryB()) if (isAExistFlag) { dispatch(queryA()) } } }
這樣利用了 redux 可以實現(xiàn)功能,在模塊 B 內調用模塊 A 的更新邏輯;但這樣邏輯就耦合了,我在模塊 A 調用模塊 B 方法 在模塊 B 調用模塊 A 的方法;但很有可能這兩個模塊是沒有其他交互的。這違反了低耦合高內聚的原則
而且書寫 redux 的一個原則就是 不要調用(dispatch)其他模塊的 action
如果你不使用 redux 如果是一個模塊內調用其他模塊的方法也是沒有做到解耦的;那如何做到解耦尼?請看方案二
方案二:利用事件系統(tǒng)如果您的項目中沒有一個全局的事件系統(tǒng),可能需要引入一個;一個簡單的事件系統(tǒng)大概是:
class EventEmitter { constructor() { this.listeners = {}; } on(type, cb, mode) { let cbs = this.listeners[type]; if (!cbs) { cbs = []; } cbs.push(cb); this.listeners[type] = cbs; return () => { this.remove(type, cb); }; } emit(type, ...args) { console.log( `%c event ${type} be triggered`, "color:rgb(20,150,250);font-size:14px", ); const cbs = this.listeners[type]; if (Array.isArray(cbs)) { for (let i = 0; i < cbs.length; i++) { const cb = cbs[i]; if (typeof cb === "function") { cb(...args); } } } } remove(type, cb) { if (cb) { let cbs = this.listeners[type]; cbs = cbs.filter(eMap => eMap.cb !== cb); this.listeners[type] = cbs; } else { this.listeners[type] = null; delete this.listeners[type]; } } } export default new EventEmitter();
這個事件系統(tǒng)具有注冊,發(fā)布,移除事件的功能。那我們怎么在剛才這個場景去使用它尼?
發(fā)布:當A模塊內數(shù)據(jù)因操作發(fā)生變化時,觸發(fā)該數(shù)據(jù)變化的事件,定義type為data1Change;
注冊:這里B模塊的注冊的時機,上述的場景為A和B模塊可能同時出現(xiàn),所以A模塊存在B模塊卻不存在。所以這個B模塊事件的監(jiān)聽選擇在B模塊組件的componentDidMount的時候注冊,在componentWillUnmount時移除
大致的代碼如下:
import EventEmitter from "eventEmitter" class A extends React.Component { handleUpdateData = () => { // 如果 A模塊存在 const { dispatch, queryB } = props dispatch(queryA()) EventEmitter.emit("data1Change") } } // B import EventEmitter from "eventEmitter" class B extends React.Component { componentDidMount() { const unlistener = EventEmitter.on("data1Change", this.handleData1Change) } componentWillUnmount() { EventEmitter.on("data1Change", this.handleData1Change) } handleData1Change = () => { const { dispatch, queryB } = this.props dispatch(queryB()) } }
這樣通過事件系統(tǒng)做到了兩個模塊之間的解耦,作為事件發(fā)布方只管發(fā)布自己的事件。兩個模塊在事件系統(tǒng)唯一的聯(lián)系就是事先定義好事件的type。
不過這也增加了幾行的代碼量,但相比帶來的優(yōu)勢來說可以不計。
其他方案歡迎大家評論
其他場景待大家補充
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/99573.html
摘要:在我看來它們的關系不會比共用開頭更深了,所以我就重新開了一個頭,但其實是基于前面寫的資源中文文檔英文文檔官方視頻學習歷程當初為了學習,看了許多的材料,中途曾經(jīng)放棄兩次,但是最后還是勇敢的拿起了它,現(xiàn)在終于勉強弄懂。 0x000 概述 這一章開始講redux,其實是承接前面的react,但其實作為一個框架來說,redux和react并沒有太多的關系,本身是獨立存在的。在我看來它們的關系不...
摘要:通過發(fā)布訂閱模式過濾數(shù)據(jù)現(xiàn)在我們已經(jīng)把應用中比較敏感的代碼放到了一些方法里面,我們還需要學習安全故事的另一半內容了。當在客戶端被調用時傳入發(fā)布器名稱,客戶端將會從發(fā)布器訂閱所有的數(shù)據(jù)。這個按鈕應該只是給任務的所有者來顯示。 通過發(fā)布訂閱模式過濾數(shù)據(jù) 現(xiàn)在我們已經(jīng)把應用中比較敏感的代碼放到了一些方法里面,我們還需要學習Meteor安全故事的另一半內容了。到現(xiàn)在為止,我們一直是假設整個整個...
摘要:同時吸取了社區(qū)大量優(yōu)秀思想,進行歸納比對。有興趣的讀者可以點擊下面的鏈接購買,再次感謝各位的支持與鼓勵懇請各位批評指正京東當當原文網(wǎng)址 在React中最小的邏輯單元是組件,組件之間如果有耦合關系就會進行通信,本文將會介紹React中的組件通信的不同方式 通過歸納范,可以將任意組件間的通信歸類為四種類型的組件間通信,分別是父子組件,爺孫組件,兄弟組件和任意組件,需要注意的是前三個也可以算...
摘要:下面我們會向大家解釋清楚為什么這個這么重要,以及它和的響應式數(shù)據(jù)流有什么關系。源碼前面鋪墊這么多就是希望大家能理解接下來要講的響應式數(shù)據(jù)流??偨Y講到這里大家應該都能夠明白的響應式數(shù)據(jù)流是如何實現(xiàn)的。 Vue、React介紹 目前前端社區(qū)比較推崇的框架有Vue 和 React,公司內部許多端都自發(fā)的將原有的老技術方案(widget + jQuery)遷移到 Vue / React上了。我...
閱讀 898·2021-11-23 09:51
閱讀 1111·2021-11-15 17:57
閱讀 1680·2021-09-22 15:24
閱讀 823·2021-09-07 09:59
閱讀 2238·2019-08-29 15:10
閱讀 1859·2019-08-29 12:47
閱讀 763·2019-08-29 12:30
閱讀 3386·2019-08-26 13:51