成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

解密傳統(tǒng)組件間通信與React組件間通信

CoderBear / 3342人閱讀

摘要:同時吸取了社區(qū)大量優(yōu)秀思想,進行歸納比對。有興趣的讀者可以點擊下面的鏈接購買,再次感謝各位的支持與鼓勵懇請各位批評指正京東當(dāng)當(dāng)原文網(wǎng)址

在React中最小的邏輯單元是組件,組件之間如果有耦合關(guān)系就會進行通信,本文將會介紹React中的組件通信的不同方式

通過歸納范,可以將任意組件間的通信歸類為四種類型的組件間通信,分別是父子組件,爺孫組件,兄弟組件和任意組件,
需要注意的是前三個也可以算作任意組件的范疇,所以最后一個是萬能方法

父子組件

父子組件間的通信分為父組件向子組件通信和子組件向父組件通信兩種情況,下面先來介紹父組件向子組件通信,
傳統(tǒng)做法分為兩種情況,分別是初始化時的參數(shù)傳遞和實例階段的方法調(diào)用,例子如下

class Child {
    constructor(name) {
        // 獲取dom引用
        this.$div = document.querySelector("#wp");

        // 初始化時傳入name
        this.updateName(name);
    }
    updateName(name) {
        // 對外提供更新的api
        this.name = name;
    
        // 更新dom
        this.$div.innerHTML = name;
    }
}

class Parent {
    constructor() {
        // 初始化階段
        this.child = new Child("yan");
        
        setTimeout(() => {
            // 實例化階段
            this.child.updateName("hou");
        }, 2000);
    }
}

在React中將兩個情況統(tǒng)一處理,全部通過屬性來完成,之所以能夠這樣是因為React在屬性更新時會自動重新渲染子組件,
下面的例子中,2秒后子組件會自動重新渲染,并獲取新的屬性值

class Child extends Component {
    render() {
        return 
{this.props.name}
} } class Parent extends Component { constructor() { // 初始化階段 this.state = {name: "yan"}; setTimeout(() => { // 實例化階段 this.setState({name: "hou"}) }, 2000); } render() { return } }

下面來看一下子組件如何向父組件通信,傳統(tǒng)做法有兩種,一種是回調(diào)函數(shù),另一種是為子組件部署消息接口

先來看回調(diào)函數(shù)的例子,回調(diào)函數(shù)的優(yōu)點是非常簡單,缺點就是必須在初始化的時候傳入,并且不可撤回,并且只能傳入一個函數(shù)

class Child {
    constructor(cb) {
        // 調(diào)用父組件傳入的回調(diào)函數(shù),發(fā)送消息
        setTimeout(() => { cb() }, 2000);
    }
}

class Parent {
    constructor() {
        // 初始化階段,傳入回調(diào)函數(shù)
        this.child = new Child(function () {
            console.log("child update")
        });
    }
}

下面來看看消息接口方法,首先需要一個可以發(fā)布和訂閱消息的基類,比如下面實現(xiàn)了一個簡單的EventEimtter,實際生產(chǎn)中可以直接使用別人寫好的類庫,比如@jsmini/event,子組件繼承消息基類,就有了發(fā)布消息的能力,然后父組件訂閱子組件的消息,即可實現(xiàn)子組件向父組件通信的功能

消息接口的優(yōu)點就是可以隨處訂閱,并且可以多次訂閱,還可以取消訂閱,缺點是略顯麻煩,需要引入消息基類

// 消息接口,訂閱發(fā)布模式,類似綁定事件,觸發(fā)事件
class EventEimtter {
    constructor() {
        this.eventMap = {};
    }
    sub(name, cb) {
        const eventList = this.eventMap[name] = this.eventMap[name] || {};
        eventList.push(cb);
    }
    pub(name, ...data) {
        (this.eventMap[name] || []).forEach(cb => cb(...data));
    }
}

class Child extends EventEimtter {
    constructor() {
        super();
        // 通過消息接口發(fā)布消息
        setTimeout(() => { this.pub("update") }, 2000);
    }
}

class Parent {
    constructor() {
        // 初始化階段,傳入回調(diào)函數(shù)
        this.child = new Child();
        
        // 訂閱子組件的消息
        this.child.sub("update", function () {
            console.log("child update")
        });
    }
}

Backbone.js就同時支持回調(diào)函數(shù)和消息接口方式,但React中選擇了比較簡單的回調(diào)函數(shù)模式,下面來看一下React的例子

class Child extends Component {
    constructor(props) {
        setTimeout(() => { this.props.cb() }, 2000);
    }
    render() {
        return 
} } class Parent extends Component { render() { return {console.log("update")}} /> } }
爺孫組件

父子組件其實可以算是爺孫組件的一種特例,這里的爺孫組件不光指爺爺和孫子,而是泛指祖先與后代組件通信,可能隔著很多層級,我們已經(jīng)解決了父子組件通信的問題,根據(jù)化歸法,很容易得出爺孫組件的答案,那就是層層傳遞屬性么,把爺孫組件通信分解為多個父子組件通信的問題

層層傳遞的優(yōu)點是非常簡單,用已有知識就能解決,問題是會浪費很多代碼,非常繁瑣,中間作為橋梁的組件會引入很多不屬于自己的屬性

在React中,通過context可以讓祖先組件直接把屬性傳遞到后代組件,有點類似星際旅行中的蟲洞一樣,通過context這個特殊的橋梁,可以跨越任意層次向后代組件傳遞消息

怎么在需要通信的組件之間開啟這個蟲洞呢?需要雙向聲明,也就是在祖先組件聲明屬性,并在后代組件上再次聲明屬性,然后在祖先組件上放上屬性就可以了,就可以在后代組件讀取屬性了,下面看一個例子

import PropTypes from "prop-types";

class Child extends Component {
    // 后代組件聲明需要讀取context上的數(shù)據(jù)
    static contextTypes = {
        text: PropTypes.string
    }
    render() {
        // 通過this.context 讀取context上的數(shù)據(jù)
        return 
{this.context.text}
} } class Ancestor extends Component { // 祖先組件聲明需要放入context上的數(shù)據(jù) static childContextTypes = { text: PropTypes.string } // 祖先組件往context放入數(shù)據(jù) getChildContext() { return {text: "yanhaijing"} } }

context的優(yōu)點是可以省去層層傳遞的麻煩,并且通過雙向聲明控制了數(shù)據(jù)的可見性,對于層數(shù)很多時,不失為一種方案;但缺點也很明顯,就像全局變量一樣,如果不加節(jié)制很容易造成混亂,而且也容易出現(xiàn)重名覆蓋的問題

個人的建議是對一些所有組件共享的只讀信息可以采用context來傳遞,比如登錄的用戶信息等

小貼士:React Router路由就是通過context來傳遞路由屬性的

兄弟組件

如果兩個組件是兄弟關(guān)系,可以通過父組件作為橋梁,來讓兩個組件之間通信,這其實就是主模塊模式

下面的例子中,兩個子組件通過父組件來實現(xiàn)顯示數(shù)字同步的功能

class Parent extends Component {
    constructor() {
        this.onChange = function (num) {
            this.setState({num})
        }.bind(this);
    }
    render() {
        return (
            
); } }

主模塊模式的優(yōu)點就是解耦,把兩個子組件之間的耦合關(guān)系,解耦成子組件和父組件之間的耦合,把分散的東西收集在一起好處非常明顯,能帶來更好的可維護性和可擴展性

任意組件

任意組件包括上面的三種關(guān)系組件,上面三種關(guān)系應(yīng)該優(yōu)先使用上面介紹的方法,對于任意的兩個組件間通信,總共有三種辦法,分別是共同祖先法,消息中間件和狀態(tài)管理

基于我們上面介紹的爺孫組件和兄弟組件,只要找到兩個組件的共同祖先,就可以將任意組件之間的通信,轉(zhuǎn)化為任意組件和共同祖先之間的通信,這個方法的好處就是非常簡單,已知知識就能搞定,缺點就是上面兩種模式缺點的疊加,除了臨時方案,不建議使用這種方法

另一種比較常用的方法是消息中間件,就是引入一個全局消息工具,兩個組件通過這個全局工具進行通信,這樣兩個組件間的通信,就通過全局消息媒介完成了

還記得上面介紹的消息基類嗎?下面的例子中,組件1和組件2通過全局event進行通信

class EventEimtter {
    constructor() {
        this.eventMap = {};
    }
    sub(name, cb) {
        const eventList = this.eventMap[name] = this.eventMap[name] || {};
        eventList.push(cb);
    }
    pub(name, ...data) {
        (this.eventMap[name] || []).forEach(cb => cb(...data));
    }
}

// 全局消息工具
const event = new EventEimtter;

// 一個組件
class Element1 extends Component {
    constructor() {
        // 訂閱消息
        event.sub("element2update", () => {console.log("element2 update")});
    }
}

// 另一個組件。
class Element2 extends Component {
    constructor() {
        // 發(fā)布消息
        setTimeout(function () { event.pub("element2update") }, 2000)
    }
}

消息中間件的模式非常簡單,利用了觀察者模式,將兩個組件之間的耦合解耦成了組件和消息中心+消息名稱的耦合,但為了解耦卻引入全局消息中心和消息名稱,消息中心對組件的侵入性很強,和第三方組件通信不能使用這種方式

小型項目比較適合使用這種方式,但隨著項目規(guī)模的擴大,達到中等項目以后,消息名字爆炸式增長,消息名字的維護成了棘手的問題,重名概率極大,沒有人敢隨便刪除消息信息,消息的發(fā)布者找不到消息訂閱者的信息等

其實上面的問題也不是沒有解決辦法,重名的問題可以通過制定規(guī)范,消息命名空間等方式來極大降低沖突,其他問題可以通過把消息名字統(tǒng)一維護到一個文件,通過對消息的中心化管理,可以讓很多問題都很容易解決

如果你的項目非常大,上面兩種方案都不合適,那你可能需要一個狀態(tài)管理工具,通過狀態(tài)管理工具把組件之間的關(guān)系,和關(guān)系的處理邏輯從組建中抽象出來,并集中化到統(tǒng)一的地方來處理,Redux就是一個非常不錯的狀態(tài)管理工具

除了Redux,還有Mobx,Rematch,reselect等工具,本文不展開介紹,有機會后面多帶帶成文,這些都是用來解決不同問題的,只要根據(jù)自己的場景選擇合適的工具就好了

總結(jié)

組件間的關(guān)系千變?nèi)f化,都可以用上面介紹的方法解決,對于不同規(guī)模的項目,應(yīng)該選擇適合自己的技術(shù)方案,上面介紹的不同方式解耦的程度是不一樣的,關(guān)于不同耦合關(guān)系的好壞,可以看我之前的文章《圖解7種耦合關(guān)系》

本文節(jié)選自我的新書《React 狀態(tài)管理與同構(gòu)實戰(zhàn)》,感興趣的同學(xué)可以繼續(xù)閱讀本書,這本書由我和前端自身技術(shù)侯策合力打磨,凝結(jié)了我們在學(xué)習(xí)、實踐 React 框架過程中的積累和心得。除了 React 框架使用介紹以外,著重剖析了狀態(tài)管理以及服務(wù)端渲染同構(gòu)應(yīng)用方面的內(nèi)容。同時吸取了社區(qū)大量優(yōu)秀思想,進行歸納比對。

本書受到百度公司副總裁沈抖、百度高級前端工程師董睿,以及知名JavaScript語言專家阮一峰、Node.js布道者狼叔、Flarum中文社區(qū)創(chuàng)始人 justjavac、新浪移動前端技術(shù)專家小爝、知乎知名博主顧軼靈等前端圈眾多專家大咖的聯(lián)合力薦。

有興趣的讀者可以點擊下面的鏈接購買,再次感謝各位的支持與鼓勵!懇請各位批評指正!

京東:https://item.jd.com/12403508....

當(dāng)當(dāng):http://product.dangdang.com/2...

原文網(wǎng)址:http://yanhaijing.com/javascr...

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/97845.html

相關(guān)文章

  • React組件通信

    摘要:組件間通信父組件中放入子組件將自身屬性與方法傳給子組件子組件即父組件的一部分所以只要父組件重新子組件也必定重新子組件接收父組件傳過來的屬性與方法調(diào)用父組件方法為父組件中的父組件子組件調(diào)用子組件自己的方法調(diào)用父組件方法父組件向子組件通信數(shù) 組件間通信 1.父組件中放入子組件,將自身屬性與方法傳給子組件,子組件即父組件的一部分,所以只要父組件重新render,子組件也必定重新render....

    chenatu 評論0 收藏0
  • React入門0x012: 組件通信

    摘要:可以看到,父級更新了,子組件也同步更新了,也就完成了父組件向子組件發(fā)起通信的目的。當(dāng)然我們也可以通過適當(dāng)?shù)慕M件設(shè)計來避免過深的組件嵌套通信。所以這就解決了遠程組件通信深度組件嵌套的問題。組件間通信可以選擇像這樣的庫來處理。 0x000 概述 這一章講組件間通信,組件通信分為很多種: 父組件向子組件發(fā)起通信 子組件向父組件發(fā)起通信 兄弟組件間通訊 遠程組件通信 在組件通信中,有一種錯...

    Tonny 評論0 收藏0
  • Vue 組件通信方式

    摘要:本身提供哪幾種通信方式首先靈感源于,支持雙向綁定,本質(zhì)還是單向數(shù)據(jù)流。跟一樣,組件間最基本的數(shù)據(jù)流是通過向子組件傳遞數(shù)據(jù)。但是在卻很少使用,因為組件可以自定義事件,即后面的組件間通信方式其實就是訂閱發(fā)布模式。 例子是在 jsrun.net 平臺編寫,不支持移動端平臺,所以本文建議在 PC 端進行閱讀。 Vue 是數(shù)據(jù)驅(qū)動的視圖框架,那么組件間的數(shù)據(jù)通信是必然的事情,那么組件間如何進行數(shù)...

    hss01248 評論0 收藏0
  • React 組件的通訊

    摘要:父組件聲明自己支持父組件提供一個函數(shù),用來返回相應(yīng)的對象子組件聲明自己需要使用我胡漢三又回來了點擊我如果是父組件向子組件單向通信,可以使用變量,如果子組件想向父組件通信,同樣可以由父組件提供一個回調(diào)函數(shù),供子組件調(diào)用,回傳參數(shù)。 在使用 React 的過程中,不可避免的需要組件間進行消息傳遞(通信),組件間通信大體有下面幾種情況: 父組件向子組件通信 子組件向父組件通信 跨級組件之間...

    dongxiawu 評論0 收藏0
  • React組件通信的幾種方式

    摘要:首次發(fā)表在個人博客需要組件之進行通信的幾種情況父組件向子組件通信子組件向父組件通信跨級組件通信沒有嵌套關(guān)系組件之間的通信父組件向子組件通信數(shù)據(jù)流動是單向的父組件向子組件通信也是最常見的父組件通過向子組件傳遞需要的信息子組件向父組件通信利用 showImg(https://segmentfault.com/img/remote/1460000012361466?w=1240&h=667)...

    yeooo 評論0 收藏0

發(fā)表評論

0條評論

CoderBear

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<