成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

react 中發(fā)布訂閱模式使用

UsherChen / 1774人閱讀

摘要:中發(fā)布訂閱模式使用場(chǎng)景怎么能將設(shè)計(jì)模式應(yīng)用到我們的項(xiàng)目中以前一直在思考這個(gè)問題。兩個(gè)模塊在事件系統(tǒng)唯一的聯(lián)系就是事先定義好事件的。

react 中發(fā)布訂閱模式使用 場(chǎng)景

怎么能將設(shè)計(jì)模式應(yīng)用到我們的 React 項(xiàng)目中?以前一直在思考這個(gè)問題。

場(chǎng)景一

模塊 A 模塊 B 需要用到同一個(gè)數(shù)據(jù) data,A 和 B 都會(huì)修改這份數(shù)據(jù),且這兩個(gè)模塊會(huì)同時(shí)存在;這時(shí)我們?nèi)绾巫龅綌?shù)據(jù)公用與各個(gè)模塊的更新?

方案一:
將這份數(shù)據(jù)作為公共的數(shù)據(jù) data,A B 模塊同時(shí)使用并更改這份數(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調(diào)用方法;
this.props.dispatch({
    type: "common_setData",
    data: [1, 2],
});

好的,第一種場(chǎng)景可以使用 redux 完美解決

方案二:待補(bǔ)充

場(chǎng)景二

A 模塊使用了 data1, B 模塊使用了 data2;A B 模塊可以修改對(duì)應(yīng)的 data;這兩份 data 結(jié)構(gòu)上不同,但是存在業(yè)務(wù)上的聯(lián)系: 當(dāng) data1 更新后需要 data2 更新;data2 更新同樣需要 data1 同步;對(duì)應(yīng)后端的兩個(gè)不同的 API。

我們整理一下

A B 使用兩份存在聯(lián)系的 data

其中一個(gè)更新需要另一個(gè)更新

兩份 data 對(duì)應(yīng)不同的 API 接口

A B 對(duì)應(yīng)兩個(gè)不同的 tab 且可能同時(shí)存在

方案一

當(dāng)其中一個(gè)數(shù)據(jù)因操作發(fā)生更新時(shí),判斷另一個(gè)模塊是否存在 如果存在則調(diào)用他的數(shù)據(jù)更新邏輯;

如果你使用了 redux,可能方便一點(diǎn):

// reducerA
// 省略B
function reducerA(state = { data: [] }, action) {
    switch(action.type) {
        case "A_setDataA": {
            return {
                ...state,
                data: action.data
            }
        }
        default: return state
    }
}

// 假設(shè)使用了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 可以實(shí)現(xiàn)功能,在模塊 B 內(nèi)調(diào)用模塊 A 的更新邏輯;但這樣邏輯就耦合了,我在模塊 A 調(diào)用模塊 B 方法 在模塊 B 調(diào)用模塊 A 的方法;但很有可能這兩個(gè)模塊是沒有其他交互的。這違反了低耦合高內(nèi)聚的原則
而且書寫 redux 的一個(gè)原則就是 不要調(diào)用(dispatch)其他模塊的 action

如果你不使用 redux 如果是一個(gè)模塊內(nèi)調(diào)用其他模塊的方法也是沒有做到解耦的;那如何做到解耦尼?請(qǐng)看方案二

方案二:利用事件系統(tǒng)

如果您的項(xiàng)目中沒有一個(gè)全局的事件系統(tǒng),可能需要引入一個(gè);一個(gè)簡(jiǎn)單的事件系統(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();

這個(gè)事件系統(tǒng)具有注冊(cè),發(fā)布,移除事件的功能。那我們?cè)趺丛趧偛胚@個(gè)場(chǎng)景去使用它尼?

發(fā)布:當(dāng)A模塊內(nèi)數(shù)據(jù)因操作發(fā)生變化時(shí),觸發(fā)該數(shù)據(jù)變化的事件,定義typedata1Change;

注冊(cè):這里B模塊的注冊(cè)的時(shí)機(jī),上述的場(chǎng)景為A和B模塊可能同時(shí)出現(xiàn),所以A模塊存在B模塊卻不存在。所以這個(gè)B模塊事件的監(jiān)聽選擇在B模塊組件的componentDidMount的時(shí)候注冊(cè),在componentWillUnmount時(shí)移除

大致的代碼如下:

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)做到了兩個(gè)模塊之間的解耦,作為事件發(fā)布方只管發(fā)布自己的事件。兩個(gè)模塊在事件系統(tǒng)唯一的聯(lián)系就是事先定義好事件的type。

不過這也增加了幾行的代碼量,但相比帶來的優(yōu)勢(shì)來說可以不計(jì)。

其他方案歡迎大家評(píng)論

其他場(chǎng)景

待大家補(bǔ)充

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/99573.html

相關(guān)文章

  • Redux入門0x101: 簡(jiǎn)介及`redux`簡(jiǎn)單實(shí)現(xiàn)

    摘要:在我看來它們的關(guān)系不會(huì)比共用開頭更深了,所以我就重新開了一個(gè)頭,但其實(shí)是基于前面寫的資源中文文檔英文文檔官方視頻學(xué)習(xí)歷程當(dāng)初為了學(xué)習(xí),看了許多的材料,中途曾經(jīng)放棄兩次,但是最后還是勇敢的拿起了它,現(xiàn)在終于勉強(qiáng)弄懂。 0x000 概述 這一章開始講redux,其實(shí)是承接前面的react,但其實(shí)作為一個(gè)框架來說,redux和react并沒有太多的關(guān)系,本身是獨(dú)立存在的。在我看來它們的關(guān)系不...

    ssshooter 評(píng)論0 收藏0
  • 翻譯 Meteor React 制作 Todos - 11 - 發(fā)布訂閱

    摘要:通過發(fā)布訂閱模式過濾數(shù)據(jù)現(xiàn)在我們已經(jīng)把應(yīng)用中比較敏感的代碼放到了一些方法里面,我們還需要學(xué)習(xí)安全故事的另一半內(nèi)容了。當(dāng)在客戶端被調(diào)用時(shí)傳入發(fā)布器名稱,客戶端將會(huì)從發(fā)布器訂閱所有的數(shù)據(jù)。這個(gè)按鈕應(yīng)該只是給任務(wù)的所有者來顯示。 通過發(fā)布訂閱模式過濾數(shù)據(jù) 現(xiàn)在我們已經(jīng)把應(yīng)用中比較敏感的代碼放到了一些方法里面,我們還需要學(xué)習(xí)Meteor安全故事的另一半內(nèi)容了。到現(xiàn)在為止,我們一直是假設(shè)整個(gè)整個(gè)...

    用戶83 評(píng)論0 收藏0
  • 解密傳統(tǒng)組件間通信與React組件間通信

    摘要:同時(shí)吸取了社區(qū)大量?jī)?yōu)秀思想,進(jìn)行歸納比對(duì)。有興趣的讀者可以點(diǎn)擊下面的鏈接購買,再次感謝各位的支持與鼓勵(lì)懇請(qǐng)各位批評(píng)指正京東當(dāng)當(dāng)原文網(wǎng)址 在React中最小的邏輯單元是組件,組件之間如果有耦合關(guān)系就會(huì)進(jìn)行通信,本文將會(huì)介紹React中的組件通信的不同方式 通過歸納范,可以將任意組件間的通信歸類為四種類型的組件間通信,分別是父子組件,爺孫組件,兄弟組件和任意組件,需要注意的是前三個(gè)也可以算...

    CoderBear 評(píng)論0 收藏0
  • 源碼解析 —— Vue的響應(yīng)式數(shù)據(jù)流

    摘要:下面我們會(huì)向大家解釋清楚為什么這個(gè)這么重要,以及它和的響應(yīng)式數(shù)據(jù)流有什么關(guān)系。源碼前面鋪墊這么多就是希望大家能理解接下來要講的響應(yīng)式數(shù)據(jù)流??偨Y(jié)講到這里大家應(yīng)該都能夠明白的響應(yīng)式數(shù)據(jù)流是如何實(shí)現(xiàn)的。 Vue、React介紹 目前前端社區(qū)比較推崇的框架有Vue 和 React,公司內(nèi)部許多端都自發(fā)的將原有的老技術(shù)方案(widget + jQuery)遷移到 Vue / React上了。我...

    LuDongWei 評(píng)論0 收藏0
  • Vue基本原理

    摘要:標(biāo)簽添加監(jiān)聽事件文本節(jié)點(diǎn)這一步我們操作頁面輸入框,可以看到以下效果,證明監(jiān)聽事件添加有效。 前言 經(jīng)過幾天的研究,發(fā)現(xiàn)學(xué)習(xí)框架的底層技術(shù),收獲頗豐,相比只學(xué)習(xí)框架的使用要來的合算;如果工作急需,快速上手應(yīng)用,掌握如何使用短期內(nèi)更加高效;如果有較多的時(shí)間來系統(tǒng)學(xué)習(xí),建議研究一下框架的等層技術(shù)、原理。 Vue、React、Angular三大框架對(duì)比 1、Vue Vue是尤雨溪編寫的一個(gè)構(gòu)建...

    firim 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<