


The content of this article is about the analysis and comparison of communication between traditional components and communication between React components (code examples). It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you. help.
The smallest logical unit in React is a component. If there is a coupling relationship between components, they will communicate. This article will introduce the different ways of component communication in React
By induction, Communication between any components can be classified into four types of inter-component communication, namely parent-child components, grandfather-grandson components, sibling components and any components.
It should be noted that the first three can also be counted as any components. category, so the last one is a universal method
Parent-child component
The communication between parent and child components is divided into two situations: communication from parent component to child component and communication from child component to parent component. Let’s first introduce the parent component. Components communicate with sub-components.
The traditional approach is divided into two situations, namely parameter passing during initialization and method invocation in the instance phase. The example is as follows
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); } }
In React, the two situations are handled uniformly. All is done through properties. The reason why this is possible is that React will automatically re-render the sub-component when the properties are updated.
In the following example, the sub-component will automatically re-render after 2 seconds and obtain the new property value
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></child> } }
Let’s take a look at how sub-components communicate with parent components. There are two traditional methods, one is the callback function, and the other is to deploy a message interface for the sub-component.
Let’s first look at the callback function. For example, the advantage of the callback function is that it is very simple. The disadvantage is that it must be passed in during initialization and cannot be withdrawn, and only one function can be passed in.
class Child { constructor(cb) { // 调用父组件传入的回调函数,发送消息 setTimeout(() => { cb() }, 2000); } } class Parent { constructor() { // 初始化阶段,传入回调函数 this.child = new Child(function () { console.log('child update') }); } }
Let's take a look at the message interface method. First, we need a A base class that can publish and subscribe to messages. For example, a simple EventEimtter
is implemented below. In actual production, you can directly use class libraries written by others, such as @jsmini/event. Subcomponents inherit the message base class. With the ability to publish messages, the parent component can then subscribe to the message of the child component to realize the function of the child component communicating with the parent component.
The advantage of the message interface is that it can be subscribed anywhere and multiple times, and it can be subscribed multiple times. You can cancel the subscription, but the disadvantage is that it is a little troublesome. You need to introduce the message base class
// 消息接口,订阅发布模式,类似绑定事件,触发事件 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 supports both callback functions and message interface methods, but React has chosen a relatively simple callback function mode. Let’s look at it below. Let’s look at an example of React
class Child extends Component { constructor(props) { setTimeout(() => { this.props.cb() }, 2000); } render() { return <p></p> } } class Parent extends Component { render() { return <child> {console.log('update')}} /> } }</child>
Grandfather and grandson component
Father and son components can actually be regarded as a special case of grandson and grandson components. The grandson and grandson components here not only refer to grandfather and grandson, but generally refer to ancestors and The communication between descendant components may be separated by many levels. We have solved the problem of parent-child component communication. According to the reduction method, it is easy to get the answer to the grandfather-grandchild component. That is to pass attributes layer by layer. The grandfather-grandchild component communication is decomposed into The problem of communication between multiple parent-child components
The advantage of layer-by-layer transfer is that it is very simple and can be solved with existing knowledge. The problem is that it will waste a lot of code and is very cumbersome. The components in the middle that serve as bridges will introduce many components that do not belong to Own properties
In React, ancestor components can pass properties directly to descendant components through context. It is a bit like the wormhole in Star Trek. Through the special bridge of context, you can cross any level to descendants. Components pass messages
How to open this wormhole between components that need to communicate? Two-way declaration is required, that is, declaring attributes on the ancestor component, declaring the attributes again on the descendant component, and then putting the attributes on the ancestor component. Then you can read the attributes on the descendant component. Here is an example
The advantage ofimport 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 is that it can save the trouble of layer-by-layer transmission and control the visibility of data through bidirectional declaration. It is a solution when there are many layers; but the disadvantages are also obvious, just like global variables. , if not controlled, it can easily cause confusion, and it is also prone to the problem of duplicate name coverage.
My personal suggestion is that some read-only information shared by all components can be transferred using context, such as logged-in user information, etc.
Tips: React Router routing is to pass routing attributes through context
Sibling components
If the two components are brothers, you can The parent component is used as a bridge to communicate between the two components. This is actually the main module mode
In the following example, the two sub-components realize the function of displaying digital synchronization through the parent component
class Parent extends Component { constructor() { this.onChange = function (num) { this.setState({num}) }.bind(this); } render() { return ( <p> <child1> <child2> </child2></child1></p> ); } }
The advantage of the main module pattern is decoupling. It decouples the coupling relationship between two sub-components into the coupling between the sub-component and the parent component. The benefits of collecting scattered things are very obvious and can bring better results. Maintainability and scalability
Any component
Any component includes the above three relationship components. The above three relationships should give priority to the methods introduced above. For any two components, There are three ways to communicate, namely common ancestor method, message middleware and state management
基于我们上面介绍的爷孙组件和兄弟组件,只要找到两个组件的共同祖先,就可以将任意组件之间的通信,转化为任意组件和共同祖先之间的通信,这个方法的好处就是非常简单,已知知识就能搞定,缺点就是上面两种模式缺点的叠加,除了临时方案,不建议使用这种方法
另一种比较常用的方法是消息中间件,就是引入一个全局消息工具,两个组件通过这个全局工具进行通信,这样两个组件间的通信,就通过全局消息媒介完成了
还记得上面介绍的消息基类吗?下面的例子中,组件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等工具,本文不展开介绍,有机会后面单独成文,这些都是用来解决不同问题的,只要根据自己的场景选择合适的工具就好。
The above is the detailed content of Analysis and comparison of communication between traditional components and communication between React components (code example). For more information, please follow other related articles on the PHP Chinese website!

去掉重复并排序的方法:1、使用“Array.from(new Set(arr))”或者“[…new Set(arr)]”语句,去掉数组中的重复元素,返回去重后的新数组;2、利用sort()对去重数组进行排序,语法“去重数组.sort()”。

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于Symbol类型、隐藏属性及全局注册表的相关问题,包括了Symbol类型的描述、Symbol不会隐式转字符串等问题,下面一起来看一下,希望对大家有帮助。

怎么制作文字轮播与图片轮播?大家第一想到的是不是利用js,其实利用纯CSS也能实现文字轮播与图片轮播,下面来看看实现方法,希望对大家有所帮助!

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于对象的构造函数和new操作符,构造函数是所有对象的成员方法中,最早被调用的那个,下面一起来看一下吧,希望对大家有帮助。

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于面向对象的相关问题,包括了属性描述符、数据描述符、存取描述符等等内容,下面一起来看一下,希望对大家有帮助。

方法:1、利用“点击元素对象.unbind("click");”方法,该方法可以移除被选元素的事件处理程序;2、利用“点击元素对象.off("click");”方法,该方法可以移除通过on()方法添加的事件处理程序。

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于BOM操作的相关问题,包括了window对象的常见事件、JavaScript执行机制等等相关内容,下面一起来看一下,希望对大家有帮助。

foreach不是es6的方法。foreach是es3中一个遍历数组的方法,可以调用数组的每个元素,并将元素传给回调函数进行处理,语法“array.forEach(function(当前元素,索引,数组){...})”;该方法不处理空数组。


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

WebStorm Mac version
Useful JavaScript development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

SublimeText3 Chinese version
Chinese version, very easy to use

Safe Exam Browser
Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

Dreamweaver Mac version
Visual web development tools
