当前位置: 首页 > 编程日记 > 正文

React是如何在后台运行的

React is a very popular JavaScript library. With over 5.5 million weekly downloads, React is enjoying great popularity. But not a lot of React developers know how React works under the hood.

React是一个非常流行JavaScript库。 每周的下载量超过550万,React非常受欢迎。 但是并不是很多React开发人员都知道React是如何工作的。

In this post, I'll try to uncover some interesting things about React which you, as a React developer, might find fascinating. Let's start at the beginning.

在这篇文章中,我将尝试揭示一些关于React的有趣的事情,作为React开发人员,您可能会着迷。 让我们从头开始。

But before we start, if you're a React developer, I have some exciting news for you! Once you complete this article, you'll get to develop something cool with React and win prizes on the way :)

但是在我们开始之前,如果您是React开发人员,那么我有一些令人振奋的消息! 完成本文后,您将可以使用React开发一些很酷的东西,并在此过程中赢取奖品:)

React是做什么的? (What does React do?)

At its very core, React basically maintains a tree for you. This tree is able to do efficient diff computations on the nodes.

从根本上讲,React基本上为您维护了一棵树。 该树能够在节点上进行高效的差异计算。

Think of your HTML code as a tree. In fact, that is exactly how the browser treats your DOM (your rendered HTML on the browser). React allows you to effectively re-construct your DOM in JavaScript and push only those changes to the DOM which have actually occurred.

将您HTML代码视为一棵树。 实际上,这正是浏览器对待DOM(您在浏览器上呈现HTML)的方式。 React允许您在JavaScript中有效地重构DOM,并将实际发生的更改仅推送到DOM。

JSX是语法糖 (JSX is syntactic sugar)

There's nothing like JSX - neither to JavaScript, nor to the browser. JSX is simply syntactic sugar for creating very specific JavaScript objects.

没有像JSX一样的东西-JavaScript和浏览器都没有。 JSX只是用于创建非常特定JavaScript对象的语法糖。

When you write something like:

当您编写类似的内容时:

const tag = <h1>Hello</h1>

what you're essentially doing is this:

您实际上在做什么是这样的:

const tag = React.createElement("h1", {}, "Hello")

You see, when you start writing nested stuff, not only is this difficult to code, but it also becomes very inconvenient to maintain such a codebase. JSX thus helps you bring the cleanliness of HTML to the power of JavaScript.

您会发现,当您开始编写嵌套的东西时,不仅很难编写代码,而且维护这样的代码库也变得非常不便。 JSX因此可以帮助您将HTML的纯净性带入JavaScript的力量。

But what does React.createElement do itself? It creates a plain old JavaScript object. In fact, you can manually call it and see for yourself!

但是React.createElement本身会做什么? 它创建一个普通的旧JavaScript对象。 实际上,您可以手动调用它并亲自查看!

You see, we've an object like this:

你看,我们有一个像这样的对象:

{$$typeof: Symbol(react.element),key: null,props: {children: "Hello"},ref: null,type: "div"
}

And if we start nesting elements like this:

如果我们开始嵌套这样的元素:

React.createElement('div', { }, 
React.createElement('p', {}, 'A p inside a div')
)

We would start getting nested objects:

我们将开始获取嵌套对象:

So now you know, once all the JSX is parsed and all the React.createElement calls have been resolved, we land with one giant nested object like above.

所以现在您知道,一旦所有的JSX都被解析并且所有的React.createElement调用都已解析,我们就可以像上面那样放置一个巨型嵌套对象。

React渲染器 (React Renderer)

Now, if you go back to the point where we start our app, you'll see that in your index.js file, you would find the following line:

现在,如果您回到启动应用程序的位置,您会在index.js文件中看到以下内容:

// .. prev codeReactDOM.render(<App />, container)

From above, we know that when <App /> has been done parsing, this is just a huge object of React elements. Then how is React able to construct actual divs and p tags out of it? Meet ReactDOM.

从上面我们知道, <App />解析完成后,这只是React元素的巨大对象。 那么React如何从中构造出实际的div和p标签呢? 认识ReactDOM。

ReactDOM in turn, recursively creates nodes depending on their 'type' property and appends them finally to the DOM.

反过来,ReactDOM根据其“类型”属性递归创建节点,并将其最终附加到DOM。

It should be clear at this point that why decoupling React from the renderers is actually a great move! What React does is, simply construct a tree of UI which could be used not only on web, but on environments like mobile too, given that a renderer is available which is able to communicate with the host OS. Here, React Native comes to play. You see, React Native uses React library, but not ReactDOM as the render. Instead, the package react-native itself is a renderer.

在这一点上应该很清楚,为什么将React与渲染器解耦实际上是一个很大的举措! React的作用是,只需构建一个UI树,不仅可以在Web上使用,而且还可以在移动设备等环境中使用,前提是可以使用能够与主机OS进行通信的渲染器。 在这里,React Native开始发挥作用。 您会看到,React Native使用React库,而不使用ReactDOM作为渲染器。 相反,包react-native本身就是一个渲染器。

We do this in a react native application to start the app:

我们在react本机应用程序中执行以下操作以启动该应用程序:

const { AppRegistry } = require('react-native')
AppRegistry.registerComponent('app', () => MainComponent)

Look! No ReactDOM. Why not? Because we don't have methods like appendChild, neither do we have a DOM like environment. Instead, for mobiles, we need support for UI directly from OS. But the React library doesn't need to know that, the renderer (React Native) takes care of that.

看! 没有ReactDOM。 为什么不? 因为我们没有诸如appendChild之类的方法,所以我们也没有类似DOM的环境。 相反,对于手机,我们需要直接从OS支持UI。 但是React库不需要知道这一点,渲染器(React Native)可以解决这个问题。

React对帐 (React Reconciliation)

When we say that React maintains a copy of DOM using virtual DOM in JavaScript, and it uses to diff it to any changes and apply it to real DOM, we don't want React to brute-force its way. React, in fact does very lazy reconciliation. React would make the least amount of changes possible, i.e. it would try to re-use elements, attributes, and even styles if possible!

当我们说React使用JavaScript中的虚拟DOM维护DOM的副本,并用来将其与任何更改进行比较并将其应用于真实DOM时,我们不希望React蛮力地实现。 React,实际上做得很懒惰。 React将尽可能少地进行更改,即,如果可能,它将尝试重用元素,属性甚至样式!

Consider this example:

考虑以下示例:

<img className="class-1" alt="stuff" />

Let's say you change this JSX expression to the below one using some condition or some state:

假设您使用某种条件或某种状态将此JSX表达式更改为以下表达式:

<img className="class-1" alt="something else" />

Now while diffing, React would see that well, the img tag makes use of the same className both in old and new trees, so why modify it. And it would just modify your alt attribute and move on.

现在,在进行比较时,React会很好地看到,img标签在新旧树中都使用了相同的className,所以为什么要对其进行修改。 它只会修改您的alt属性并继续前进。

However, there's a catch. Because we don't want React to do a lot of computation on diffing part, React would assume that if a parent has changed, its containing subtree has definitely changed. For example:

但是,有一个陷阱。 因为我们不希望React在差异部分进行大量计算,所以React会假设如果父对象已更改,则其包含的子树肯定已更改。 例如:

<div className="class-1"><p>I did not change</p>
</div>

If you change this JSX to the below using condition/state:

如果使用条件/状态将此JSX更改为以下内容:

<p className="class-1"><p>I did not change</p>
</p>

Although you could see that we don't need to re-create the inner p tag, but React has no way of knowing that while traversing the tree from top (unless, of course you perform heavy tree diffing, which are much expensive algorithms than the heuristic O(n) react follows for diffing). So, React decides to destroy all children (i.e. calling their cleanup functions in useEffect, or componentWillUnmount in class based components) and re-create the children from scratch.

尽管您可以看到我们不需要重新创建内部p标签,但是React从顶部遍历树时并没有办法知道(除非您执行繁重的树差异处理,这比然后进行启发式O(n)React进行扩散)。 因此,React决定销毁所有子项(即在useEffect中调用其清理函数,或在基于类的组件中调用componentWillUnmount)并从头开始重新创建子项。

React键 (React Keys)

When adding/removing elements in a node, React would simply loop over the children in old tree and children in the new tree of the node and mark the places where it needs to perform any addition/removal. But this has a disadvantage without additional help from developer. Consider this example:

在节点中添加/删除元素时,React会简单地循环遍历该节点的老树中的孩子和新树中的孩子,并标记需要执行任何添加/删除的位置。 但这有一个缺点,即没有开发人员的额外帮助。 考虑以下示例:

<ul><li>A</li><li>B</li>
</ul>

Consider this is changed to the below by condition/state:

请考虑根据条件/状态将其更改为以下内容:

<ul><li>Z</li><li>A</li><li>B</li>
<ul>

Now, when React would start comparing the two lists for difference, it would find the difference at child node 1, would mutate the old A to new Z, then again at child node 2, would mutate it from the old B to new A, and then finally append the new B node.

现在,当React将开始比较两个列表的差异时,它将发现在子节点1上的差异,将旧的A突变为新的Z,然后在子节点2上再次将其从旧的B突变为新的A,然后最后追加新的B节点。

However, a better way would've been to preserve the existing A and B nodes and just prepend the Z node. But how would React know about that? React keys would help.

但是,更好的方法是保留现有的A和B节点,而仅在Z节点之前。 但是React怎么知道呢? React键会有所帮助。

Keys just provide a nice way to React to know which elements have changed or not changed while diffing. Now, instead of comparing the whole element, React would compare the keys of the children to see which element needs to be added/removed. The below way is an efficient way of performing the same thing:

键只是提供了一种很好的方式来让React知道差异时哪些元素已更改或未更改。 现在,React不再比较整个元素,而是比较子元素的键,以查看需要添加/删除的元素。 以下方法是执行相同操作的有效方法:

<ul><li key="A">A</li><li key="B">B</li>
</ul>

Now, if this gets changed to:

现在,如果将其更改为:

<ul><li key="Z">Z</li><li key="A">A</li><li key="B">B</li>
</ul>

React would now know that keys 'A' and 'B' already exists, so we just need to add the new element with key 'Z'.

现在,React将知道键“ A”和“ B”已经存在,因此我们只需要添加具有键“ Z”的新元素。

Are you a React developer? Show off your React skills by developing a 3 minute interactive game in React and win hoodies, shirts and coffee mugs! Take part in codecomp by joining codedamn's discord server here

您是React开发人员吗? 通过在React中开发一个3分钟的互动游戏来展示您的React技能 ,并赢得连帽衫,衬衫和咖啡杯 通过在此处加入Codedamn的Discord服务器参与codecomp

So these were some important concepts I believe would be really helpful for you as a React developers to start understanding the core of React and how it actually works. Feel free to pass down any suggestions or questions you have about the same.

因此,这些是一些重要的概念,我认为作为React开发人员,这些知识对您真正了解React的核心及其实际工作方式将非常有帮助。 随意传递任何关于您的建议或问题。

You can follow me on twitter for more JS/coding tweets and things. Peace!

您可以在Twitter上关注我,以了解更多JS /编码推文和其他内容。 和平!

翻译自: https://www.freecodecamp.org/news/react-under-the-hood/

相关文章:

H5播放视频流

代码 <html> <head> <title>视频直播</title> <meta charset"utf-8"> <link href"http://vjs.zencdn.net/5.5.3/video-js.css" rel"stylesheet"> <!-- If youd like to support IE8 --> <!-…

获取Java系统相关信息

1 package com.test;2 3 import java.util.Properties;4 import java.util.Map.Entry;5 6 import org.junit.Test;7 8 public class SystemTest {9 10 /** 11 * 获取Java系统相关信息 12 * throws Exception 13 */ 14 Test 15 public void testSys…

如何使用FaunaDB + GraphQL

I have one or two projects I maintain on Netlify, in addition to hosting my blog there. It’s an easy platform to deploy to, and has features for content management (CMS) and lambda functions (by way of AWS).除了在其中托管我的博客外&#xff0c;我在Netlify上…

POJ 1414 Life Line(搜索)

题意&#xff1a; 给定一块正三角形棋盘&#xff0c;然后给定一些棋子和空位&#xff0c;棋子序号为a&#xff08;1<a<9)&#xff0c;group的定义是相邻序号一样的棋子。 然后到C&#xff08;1<N<9&#xff09;棋手在空位放上自己序号C的棋子&#xff0c; 放完后&a…

MySQL_数据库操作语句

ZC&#xff1a;数据库名/表名/字段名 都使用小写字母 1、 创建 数据库 和 表 的时候&#xff0c;都要指定 编码方式为 utf-8 ! ! ! 因为 执行命令“show variables like char%;”后可以看到 character_set_database 的值为 latin1&#xff0c;即 默认创建数据库是使用的 字符编…

H5打开预览PDF,PPT等文件

实现代码&#xff1a; pdfUrl 写你的文件路径 <iframe :src"//www.xdocin.com/xdoc?_functo&_formathtml&_cache1&_xdocpdfUrl"width"100%"height"100%"frameborder"0"> </iframe> 可以直接打开看

广播代码_代码广播:专为编码而设计的24/7音乐

广播代码阅读本文时&#xff0c;您可以继续阅读Code Radio。 (You can go ahead and start listening to Code Radio while you read this) Most developers I know listen to music while they code. When the meetings are over, the headphones come out.我认识的大多数开发…

从 Android 静音看正确的查bug的姿势?

0、写在前面 没抢到小马哥的红包&#xff0c;无心回家了&#xff0c;回公司写篇文章安慰下自己TT。。话说年关难过&#xff0c;bug多多&#xff0c;时间久了难免头昏脑热&#xff0c;不辨朝暮&#xff0c;难识乾坤。。。艾玛&#xff0c;扯远了&#xff0c;话说谁没踩过坑&…

SecureCRT中sqlplus,使用Backspace删除时 ^H^H

在“Session Options” - "Terminal" - "Mapped Keys" - "Other mappings"&#xff0c;选择“Backspace sends delete”。转载于:https://www.cnblogs.com/Clark-cloud-database/p/7813867.html

在vue中使用vuex,修改state的值示例

1、 安装 vuex npm install vuex -S 2、在目录下创建store文件 3、 在store.js编辑一个修改state的方法 然后在mian.js中全局引入 最后在组件中使用 这个的功能是运用mutations 修改state中的值

软件开发 自由职业_自由职业? 这里有7个可以出售软件开发服务的地方

软件开发 自由职业Web developers need clients. This is true whether you are a full-time freelancer or you freelance on the side.Web开发人员需要客户。 无论您是全职自由职业者&#xff0c;还是身旁的自由职业者&#xff0c;都是如此。 So if youve ever asked: "…

生成SSH key

1、打开终端&#xff0c;输入下面的代码 &#xff0c;注意&#xff1a;$your_email为占位符&#xff0c;此处输入你自己的email ssh-keygen -t rsa -C "$your_email" 2、查看生成的公钥&#xff0c;输入下面的代码 cat ~/.ssh/id_rsa.pub 3、复制公钥&#xff08;公钥…

[转载]二叉树(BST,AVT,RBT)

二叉查找树(Binary Search Tree)是满足如下性质的二叉树&#xff1a;①若它的左子树非空&#xff0c;则左子树上所有结点的值均小于根结点的值&#xff1b;②若它的右子树非空&#xff0c;则右子树上所有结点的值均大于根结点的值&#xff1b;③左、右子树本身又各是一棵二叉查…

Invalid Host header 问题解决

出现该问的原因&#xff1a; 因为新版的 webpack-dev-server 出于安全考虑&#xff0c;默认检查 hostname&#xff0c;如果hostname不是配置内的就不能访问。 解决办法&#xff1a;设置跳过host检查 打开你的项目全局搜索 devServer &#xff0c;在 devServer 里面添加 &quo…

react hooks使用_为什么要使用React Hooks?

react hooks使用The first thing you should do whenever youre about to learn something new is ask yourself two questions -每当您要学习新东西时&#xff0c;应该做的第一件事就是问自己两个问题- Why does this thing exist? 为什么这东西存在&#xff1f; What probl…

算法 - 字符串匹配

http://blog.csdn.net/linhuanmars/article/details/20276833 转载于:https://www.cnblogs.com/qlky/p/7817471.html

工作流入门链接

百度百科-工作流 http://baike.baidu.com/link?urlZjElBNByyZz_ItLtd_Uqt3Sadcwv0-4CDO806vKQWJDuUOFybbkzpg8GOB1EU71w8bT4x64RoRXBrFXa7o_dK 企业应用工作流的好处http://jingyan.baidu.com/article/90895e0fe9c56164ec6b0b24.html工作流管理的好处http://blog.sina.com.cn/…

uniapph5配置index.html模板路径不生效解决办法

很简单&#xff0c;关闭应用再重新启动试试&#xff0c;还不行的话&#xff0c;重启IDE

终端软件升级功能开发_5个很棒的终端技巧可帮助您升级为开发人员

终端软件升级功能开发There are plenty of beginner tutorials around that help you learn command line basics, such as cd, ls, pwd and so on...but what about that fancy magic youve seen more experienced developers use?周围有很多初学者教程可以帮助您学习命令行基…

自定义左右侧滑菜单

实现效果&#xff1a; 左右侧滑菜单&#xff0c;侧滑栏占主屏比为60%监听触控&#xff0c;自定义滑动动画&#xff0c;当侧边栏滑动超过50%松开触控将自动滑动到60%&#xff0c;未超过50%松开触控回归侧边栏隐藏为主屏设置蒙版效果&#xff0c;根据侧滑菜单的占屏比设置主屏蒙版…

uniapp设置模板路径页面样式混乱解决办法

乱了就在html里面加上下面这行代码试试 <link rel"stylesheet" href"<% BASE_URL %>static/index.css" /> <meta name"viewport" content"widthdevice-width, initial-scale1.0, user-scalableno, minimum-scale1.0, maxim…

JavaScript获取当前日期,昨天,今天日期以及任意天数间隔日期

<script language"JavaScript" type"text/javascript"> function GetDateStr(AddDayCount) { var dd new Date(); dd.setDate(dd.getDate()AddDayCount);//获取AddDayCount天后的日期 var y dd.getYear(); var m dd.getMonth()1;//获取当前月份…

snapd_snapd使管理Nextcloud变得轻而易举

snapdAs I’ve described in both my Linux in Action book and Linux in Motion course, Nextcloud is a powerful way to build a file sharing and collaboration service using only open source software running on your own secure infrastructure. It’s DropBox, Skyp…

atitit.跨架构 bs cs解决方案. 自定义web服务器的实现方案 java .net jetty  HttpListener...

atitit.跨架构 bs cs解决方案. 自定义web服务器的实现方案 java .net jetty HttpListener 1. 自定义web服务器的实现方案&#xff0c;基于原始socket vs 基于tcpListener vs 基于HttpListener1 2. download1 3. Lib3 4. Code3 5. HttpListener类4 6. Reef5 1. 自定义web服务器…

Python高级函数--map/reduce

名字开头大写 后面小写&#xff1b;练习&#xff1a; 1 def normalize(name): 2 return name[0].upper() name[1:].lower() 3 L1 [adam, LISA, barT] 4 L2 list(map(normalize, L1)) 5 print(L2) reduce求积&#xff1a; 1 from functools import reduce 2 3 def prod(…

样式集(9) - 切换Tab菜单

先上效果图 下面是以vue实现的示例代码&#xff1a; 代码解析&#xff1a; 很简单的代码&#xff0c;直接复制粘贴使用吧~ 别忘记一键三连哦&#xff0c;点赞&#xff0c;收藏&#xff0c;关注&#xff0c;谢谢~ 后续持续更新更多干货哦&#xff01;&#xff01; <temp…

python字典{:4}_Python字典101:详细的视觉介绍

python字典{&#xff1a;>4}欢迎 (Welcome) In this article, you will learn how to work with Python dictionaries, an incredibly helpful built-in data type that you will definitely use in your projects.在本文中&#xff0c;您将学习如何使用Python字典&#xff…

asp.net提交危险字符处理方法之一

在form表单提交前&#xff0c;可以在web页面&#xff0c;submit按钮的click事件中&#xff0c;使用js函数对&#xff0c;可能有危险字符的内容进行编码。 有3个函数可用&#xff1a; encodeURI() 函数可把字符串作为 URI 进行编码。 escape() 函数可对字符串进行编码&#xff0…

mysql帐号,权限管理

-> use mysql; //选择数据库 -> select host,user,password from user; //查询已有用户 -> insert into user (host,user,password) values(localhost,kiscms,password(kiscms)); //插入一个用户 -> select host,user,password from user; //再次查询用户 -> fl…

样式集(10) - 滑动删除功能实现,VUE完整源码附效果图

先看效果图 实现方式&#xff1a; 使用 scroll-view 标签&#xff0c;进行横向滑动&#xff0c;达到左滑出现删除按钮&#xff0c; 注&#xff1a;如果不是使用uni-app或者小程序框架&#xff0c;没有 scroll-view 组件的话可以通过CSS实现哦 下面看uni-app的实现代码&#…