이 기사의 내용은 전통적인 구성 요소 간의 통신과 React 구성 요소 간의 통신(코드 예제)에 대한 분석 및 비교에 대한 것입니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다. 당신에게.
React에서 가장 작은 논리 단위는 컴포넌트입니다. 컴포넌트 간에 결합 관계가 있으면 통신하게 됩니다. 이 글에서는 React에서 컴포넌트 통신의 다양한 방법을 소개합니다
#🎜🎜 # 귀납을 통해 모든 구성 요소 간의 통신은 구성 요소 간 통신의 네 가지 유형, 즉 부모-자식 구성 요소, 할아버지-손자 구성 요소, 형제 구성 요소 및 모든 구성 요소로 분류될 수 있습니다. 처음 세 가지에 유의해야 합니다. 어떤 컴포넌트의 카테고리로 간주되므로 마지막은 보편적인 방법입니다
전통적인 접근 방식은 매개 변수 전달이라는 두 가지 상황으로 나뉩니다. 인스턴스 단계에서 초기화 및 메서드 호출 중 예시는 다음과 같습니다.
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); } }
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') }); } }
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')}} /> } }
EventEimtter
grandfather and grandson 컴포넌트부모-자식 컴포넌트는 실제로 할아버지로 간주될 수 있습니다. 여기서 손자 컴포넌트는 특별한 경우가 아닙니다. 할아버지와 손자만을 지칭하지만 일반적으로 조상과 자손 구성 요소 간의 통신을 의미하며 이는 여러 수준으로 구분될 수 있습니다. 우리는 부모-자식 구성 요소 통신 문제를 해결했습니다. 할아버지-손자 컴포넌트, 즉 속성을 레이어별로 전달하는 방식으로 답을 얻기 쉽습니다. 할아버지-손자 컴포넌트 통신을 여러 부모-자식 컴포넌트의 통신으로 분해하는 문제
레이어별 전송의 장점은 매우 간단하다는 것입니다. 문제는 많은 코드를 낭비하고 중간에 브리지 역할을 하는 구성 요소가 도입된다는 것입니다.
통신이 필요한 구성 요소 간에 이 웜을 여는 방법 구멍은 어디에 있나요? 양방향 선언이 필요합니다. 즉, 조상 컴포넌트에 속성을 선언하고, 자손 컴포넌트에 속성을 다시 선언한 다음, 조상 컴포넌트에 속성을 넣는 방법을 살펴보겠습니다. 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'} } }
팁: 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>
);
}
}
基于我们上面介绍的爷孙组件和兄弟组件,只要找到两个组件的共同祖先,就可以将任意组件之间的通信,转化为任意组件和共同祖先之间的通信,这个方法的好处就是非常简单,已知知识就能搞定,缺点就是上面两种模式缺点的叠加,除了临时方案,不建议使用这种方法
另一种比较常用的方法是消息中间件,就是引入一个全局消息工具,两个组件通过这个全局工具进行通信,这样两个组件间的通信,就通过全局消息媒介完成了
还记得上面介绍的消息基类吗?下面的例子中,组件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 중국어 웹사이트의 기타 관련 기사를 참조하세요!