RN EventBus實(shí)現(xiàn)跨組件間通信

寫(xiě)在前面

雖然有一定的移動(dòng)APP開(kāi)發(fā)經(jīng)驗(yàn),但RN技術(shù)我還是一個(gè)小白,上一篇對(duì)路由等有了一定的了解,這篇文章將著重解決RN跨組件進(jìn)行通信的方式。實(shí)現(xiàn)的效果是,A界面跳轉(zhuǎn)B界面,B界面進(jìn)行狀態(tài)的修改,然后A界面做出相應(yīng)的數(shù)值變化。

效果展示

// 進(jìn)入界面A
監(jiān)聽(tīng)界面:componentWillMount
進(jìn)行監(jiān)聽(tīng)
// 進(jìn)入界面B并發(fā)布消息
界面監(jiān)聽(tīng)回傳值 傳遞數(shù)值
// 退出界面A
監(jiān)聽(tīng)界面:componentWillUnmount
取消監(jiān)聽(tīng)

ok就是如上日志的效果,生命周期開(kāi)始注冊(cè),然后結(jié)束的時(shí)候取消監(jiān)聽(tīng)即可

EventBus源碼

class EventBus {
    constructor() {
        this.events = this.events || {};
    }
}

//構(gòu)造函數(shù)需要存儲(chǔ)event事件
//發(fā)布事件,參數(shù)是事件的type和需要傳遞的參數(shù)
EventBus.prototype.emit = function (type, ...args) {
    let e;
    e = this.events[type];
    // 查看這個(gè)type的event有多少個(gè)回調(diào)函數(shù),如果有多個(gè)需要依次調(diào)用。
    if (Array.isArray(e)) {
        for (let i = 0; i < e.length; i++) {
            e[i].apply(this, args);
        }
    } else {
        e.apply(this, args);
    }
};

//監(jiān)聽(tīng)函數(shù),參數(shù)是事件type和觸發(fā)時(shí)需要執(zhí)行的回調(diào)函數(shù)
EventBus.prototype.addListener = function (type, fun) {
    const e = this.events[type];
    let currentIndex = -1
    if (!e) {   //如果從未注冊(cè)過(guò)監(jiān)聽(tīng)函數(shù),則將函數(shù)放入數(shù)組存入對(duì)應(yīng)的鍵名下
        this.events[type] = [fun];
        currentIndex = 0
    } else {  //如果注冊(cè)過(guò),則直接放入
        e.push(fun);
        //獲取當(dāng)前組件監(jiān)聽(tīng)函數(shù),在觀察函數(shù)數(shù)組中的索引,移除監(jiān)聽(tīng)時(shí)使用
        currentIndex = this.events[type].length - 1
    }
    return { type, index: currentIndex}
};


//移除監(jiān)聽(tīng)
EventBus.prototype.remove = function (subscribe) {
    let { type, index } = subscribe
    let e;
    e = this.events[type];
    // 查看這個(gè)type的event有多少個(gè)回調(diào)函數(shù),如果有多個(gè)需要依次調(diào)用。
    if (Array.isArray(e)) {
        //監(jiān)聽(tīng)的函數(shù)為空,則空處理
        if (e.length === 0) {
            return
        } else if (e.length === 1) {
            //只有一個(gè)監(jiān)聽(tīng)的函數(shù),則直接移除監(jiān)聽(tīng)
            e.splice(0, 1)
        } else {
            //如果同一個(gè)key存在多個(gè)監(jiān)聽(tīng)函數(shù),只移除當(dāng)前組件監(jiān)聽(tīng)函數(shù)
            for (let i = 0; i < e.length; i++) {
                if (index > 0 && i === index) {
                    e.splice(index, 1)
                }
            }
        }
    } else {
        e = []
    }
};

//移除所有監(jiān)聽(tīng)
EventBus.prototype.removeAll = function () {
    //移除所有監(jiān)聽(tīng)函數(shù)
    if (this.events.length > 0) {
        this.events.length = 0;
    }
};

const eventBus = new EventBus();
export default eventBus;

具體代碼使用

PageA 進(jìn)行注冊(cè)

               // 監(jiān)聽(tīng)并設(shè)置狀態(tài)改變剛更新UI 
        componentWillMount(): void {
            console.log('監(jiān)聽(tīng)界面:componentWillMount');
            console.log('進(jìn)行監(jiān)聽(tīng)');
            this.subscribe = EventBus.addListener("notify", data => {
                console.log("界面監(jiān)聽(tīng)回傳值", data);
                this.setState({
                    show:data
                })
            });
        }
                // 取消監(jiān)聽(tīng)以放置重復(fù)注冊(cè)
        componentWillUnmount(): void {
            console.log('監(jiān)聽(tīng)界面:componentWillUnmount');
            console.log('取消監(jiān)聽(tīng)');
            EventBus.remove(this.subscribe);
        }

PageB觸發(fā)

EventBus.emit('notify','傳遞數(shù)值');

好了如上就是全部的使用了

拓展

由于受了Android開(kāi)發(fā)的影響,始終對(duì)EventBus情有獨(dú)鐘,應(yīng)用vue也是如此,但我們也需要對(duì)其基本的父子組件通信的學(xué)習(xí)以及了解,如props等父子通信是要會(huì)的。這是我們通信學(xué)習(xí)的第一步,后面還需要對(duì)redux進(jìn)行深入的學(xué)習(xí)。既然開(kāi)始了,就一定要百分百的付出。

參考文章

React組件通信——Event Bus
React Native Event Bus,消息總線(xiàn)
React Native組件生命周期

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容