>  기사  >  웹 프론트엔드  >  기존 컴포넌트 간 통신과 React 컴포넌트 간 통신 분석 및 비교(코드 예시)

기존 컴포넌트 간 통신과 React 컴포넌트 간 통신 분석 및 비교(코드 예시)

不言
不言원래의
2018-09-17 15:57:211194검색

이 기사의 내용은 전통적인 구성 요소 간의 통신과 React 구성 요소 간의 통신(코드 예제)에 대한 분석 및 비교에 대한 것입니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다. 당신에게.

React에서 가장 작은 논리 단위는 컴포넌트입니다. 컴포넌트 간에 결합 관계가 있으면 통신하게 됩니다. 이 글에서는 React에서 컴포넌트 통신의 다양한 방법을 소개합니다

#🎜🎜 # 귀납을 통해 모든 구성 요소 간의 통신은 구성 요소 간 통신의 네 가지 유형, 즉 부모-자식 구성 요소, 할아버지-손자 구성 요소, 형제 구성 요소 및 모든 구성 요소로 분류될 수 있습니다.

처음 세 가지에 유의해야 합니다. 어떤 컴포넌트의 카테고리로 간주되므로 마지막은 보편적인 방법입니다

Parent-child 컴포넌트

상위-하위 컴포넌트 간의 통신은 다음과 같이 나뉩니다. 부모 컴포넌트에서 자식 컴포넌트로의 통신과 자식 컴포넌트에서 부모 컴포넌트로의 통신 먼저 부모 컴포넌트와 자식 컴포넌트 간의 통신을 소개하겠습니다.

전통적인 접근 방식은 매개 변수 전달이라는 두 가지 상황으로 나뉩니다. 인스턴스 단계에서 초기화 및 메서드 호출 중 예시는 다음과 같습니다.

class Child {
    constructor(name) {
        // 获取dom引用
        this.$p = document.querySelector('#wp');

        // 初始化时传入name
        this.updateName(name);
    }
    updateName(name) {
        // 对外提供更新的api
        this.name = name;
    
        // 更新dom
        this.$p.innerHTML = name;
    }
}

class Parent {
    constructor() {
        // 初始化阶段
        this.child = new Child('yan');
        
        setTimeout(() => {
            // 实例化阶段
            this.child.updateName('hou');
        }, 2000);
    }
}
#🎜 🎜#React에서는 두 상황이 균일하게 처리되며 모두 속성을 통해 수행됩니다. 속성이 업데이트되면 하위 구성요소를 다시 렌더링합니다. 아래 예에서는 하위 구성요소가 2초 후에 자동으로 다시 렌더링되고 새 속성 값을 가져옵니다.#🎜 🎜#
class Child extends Component {
    render() {
        return <p>{this.props.name}</p>
    }
}

class Parent extends Component {
    constructor() {
        // 初始化阶段
        this.state = {name: 'yan'};

        setTimeout(() => {
            // 实例化阶段
            this.setState({name: 'hou'})
        }, 2000);
    }
    render() {
        return <Child name={this.state.name} />
    }
}

하위 구성 요소가 상위 구성 요소와 어떻게 통신하는지 살펴보겠습니다. 두 가지 전통적인 방법이 있는데, 하나는 콜백 함수이고 다른 하나는 하위 구성 요소 배포 메시지 인터페이스를 위한 것입니다
# 🎜🎜#먼저 콜백 함수의 예를 살펴보겠습니다. 콜백 함수의 장점은 매우 간단하다는 점입니다. 단점은 초기화 시 전달해야 하고 철회할 수 없으며 하나의 함수만 전달할 수 있다는 것입니다. in# 🎜🎜#

class Child {
    constructor(cb) {
        // 调用父组件传入的回调函数,发送消息
        setTimeout(() => { cb() }, 2000);
    }
}

class Parent {
    constructor() {
        // 初始化阶段,传入回调函数
        this.child = new Child(function () {
            console.log('child update')
        });
    }
}
메시지 인터페이스 메서드를 살펴보겠습니다. 먼저 메시지를 게시하고 구독할 수 있는 기본 클래스가 필요합니다. 예를 들어 실제로는 아래에 간단한

이 구현되어 있습니다. 프로덕션의 경우 @jsmini/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));
    }
}

class Child extends EventEimtter {
    constructor() {
        super();
        // 通过消息接口发布消息
        setTimeout(() => { this.pub('update') }, 2000);
    }
}

class Parent {
    constructor() {
        // 初始化阶段,传入回调函数
        this.child = new Child();
        
        // 订阅子组件的消息
        this.child.sub('update', function () {
            console.log('child update')
        });
    }
}
Backbone.js도 콜백 함수와 메시지 인터페이스 모드를 지원하지만 React는 상대적으로 간단한 콜백 함수 모드를 살펴보겠습니다. React의 예

class Child extends Component {
    constructor(props) {
        setTimeout(() => { this.props.cb() }, 2000);
    }
    render() {
        return <p></p>
    }
}

class Parent extends Component {
    render() {
        return <Child cb={() => {console.log('update')}} />
    }
}
EventEimttergrandfather and grandson 컴포넌트

부모-자식 컴포넌트는 실제로 할아버지로 간주될 수 있습니다. 여기서 손자 컴포넌트는 특별한 경우가 아닙니다. 할아버지와 손자만을 지칭하지만 일반적으로 조상과 자손 구성 요소 간의 통신을 의미하며 이는 여러 수준으로 구분될 수 있습니다. 우리는 부모-자식 구성 요소 통신 문제를 해결했습니다. 할아버지-손자 컴포넌트, 즉 속성을 레이어별로 전달하는 방식으로 답을 얻기 쉽습니다. 할아버지-손자 컴포넌트 통신을 여러 부모-자식 컴포넌트의 통신으로 분해하는 문제

레이어별 전송의 장점은 매우 간단하다는 것입니다. 문제는 많은 코드를 낭비하고 중간에 브리지 역할을 하는 구성 요소가 도입된다는 것입니다.

React에서 상위 구성요소는 컨텍스트를 통해 직접 속성을 추가할 수 있습니다. 하위 구성요소에 전달하는 것은 컨텍스트라는 특별한 브리지를 통해 메시지를 전달하는 Star Trek의 웜홀과 약간 비슷합니다. 모든 레벨의 하위 구성 요소에 전달될 수 있습니다.

통신이 필요한 구성 요소 간에 이 웜을 여는 방법 구멍은 어디에 있나요? 양방향 선언이 필요합니다. 즉, 조상 컴포넌트에 속성을 선언하고, 자손 컴포넌트에 속성을 다시 선언한 다음, 조상 컴포넌트에 속성을 넣는 방법을 살펴보겠습니다. an example #🎜🎜 #

import PropTypes from 'prop-types';

class Child extends Component {
    // 后代组件声明需要读取context上的数据
    static contextTypes = {
        text: PropTypes.string
    }
    render() {
        // 通过this.context 读取context上的数据
        return <p>{this.context.text}</p>
    }
}


class Ancestor extends Component {
    // 祖先组件声明需要放入context上的数据
    static childContextTypes = {
        text: PropTypes.string
    }
    // 祖先组件往context放入数据
    getChildContext() {
        return {text: 'yanhaijing'}
    }
}
Context의 장점은 레이어별 전송의 수고를 덜 수 있고, 양방향 선언을 통해 데이터의 가시성을 제어할 수 있다는 점입니다. 레이어; 그러나 단점도 분명합니다. 전역 변수가 동일하므로 제어하지 않으면 혼동되기 쉽고

My입니다. 개인적인 제안은 로그인과 같은 모든 구성 요소가 공유하는 일부 읽기 전용 정보가 컨텍스트를 사용하여 전달될 수 있다는 것입니다.

팁: React Router 라우팅은 라우팅 속성을 전달하는 것입니다. context를 통해

Brother 컴포넌트

# 🎜🎜#두 컴포넌트가 형제인 경우 상위 컴포넌트는 두 컴포넌트 간 통신을 위한 브리지로 사용될 수 있습니다. 메인 모듈 모드

다음 예에서는 두 개의 하위 구성 요소가 통과합니다. 상위 구성 요소는 디지털 동기화 표시 기능을 구현하는 데 사용됩니다

class Parent extends Component {
    constructor() {
        this.onChange = function (num) {
            this.setState({num})
        }.bind(this);
    }
    render() {
        return (
            <p>
                <Child1 num={this.state.num} onChange={this.onChange}>
                <Child2 num={this.state.num} onChange={this.onChange}>
            </p>
        );
    }
}
메인 모듈의 장점 모드는 두 하위 구성 요소 간의 결합 관계를 하위 구성 요소와 상위 구성 요소 간의 결합으로 분리하는 분리입니다. 🎜🎜#Any 컴포넌트

Any 컴포넌트에는 위의 세 가지 관계 컴포넌트가 포함되어 있으며, 위 세 가지 관계는 위에서 소개한 방법보다 우선순위를 두어야 합니다. 두 컴포넌트 간의 통신에는 총 세 가지 방법이 있습니다. 공통 조상 방법, 메시지 미들웨어 및 상태 관리

基于我们上面介绍的爷孙组件和兄弟组件,只要找到两个组件的共同祖先,就可以将任意组件之间的通信,转化为任意组件和共同祖先之间的通信,这个方法的好处就是非常简单,已知知识就能搞定,缺点就是上面两种模式缺点的叠加,除了临时方案,不建议使用这种方法

另一种比较常用的方法是消息中间件,就是引入一个全局消息工具,两个组件通过这个全局工具进行通信,这样两个组件间的通信,就通过全局消息媒介完成了

还记得上面介绍的消息基类吗?下面的例子中,组件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() {
        // 发布消息
        setTimeout(function () { event.pub('element2update') }, 2000)
    }
}

消息中间件的模式非常简单,利用了观察者模式,将两个组件之间的耦合解耦成了组件和消息中心+消息名称的耦合,但为了解耦却引入全局消息中心和消息名称,消息中心对组件的侵入性很强,和第三方组件通信不能使用这种方式

小型项目比较适合使用这种方式,但随着项目规模的扩大,达到中等项目以后,消息名字爆炸式增长,消息名字的维护成了棘手的问题,重名概率极大,没有人敢随便删除消息信息,消息的发布者找不到消息订阅者的信息等

其实上面的问题也不是没有解决办法,重名的问题可以通过制定规范,消息命名空间等方式来极大降低冲突,其他问题可以通过把消息名字统一维护到一个文件,通过对消息的中心化管理,可以让很多问题都很容易解决

如果你的项目非常大,上面两种方案都不合适,那你可能需要一个状态管理工具,通过状态管理工具把组件之间的关系,和关系的处理逻辑从组建中抽象出来,并集中化到统一的地方来处理,Redux就是一个非常不错的状态管理工具

除了Redux,还有Mobx,Rematch,reselect等工具,本文不展开介绍,有机会后面单独成文,这些都是用来解决不同问题的,只要根据自己的场景选择合适的工具就好。

위 내용은 기존 컴포넌트 간 통신과 React 컴포넌트 간 통신 분석 및 비교(코드 예시)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.