React入门指南

by Ankita Masand

通过Ankita Masand

React入门指南 (A beginner’s guide to getting started with React)

In this tutorial, I’ll first help you understand why Facebook felt the need to build a library called React. I’ll cover all the basic concepts that you’d need to create your first React app. This tutorial aims to explain React by clearly explaining its fundamentals like the use of JSX and ES6, building stateful & stateless components, React Elements, virtual DOM and the diffing algorithm.

在本教程中,我将首先帮助您理解为什么Facebook认为需要建立一个名为React的库。 我将介绍创建第一个React应用程序所需的所有基本概念。 本教程旨在通过清晰地解释其基本知识来解释React,例如使用JSX和ES6,构建有状态和无状态组件,React Elements,虚拟DOM和diffing算法

The web has evolved from just being a bunch of static HTML pages to reliable, interactive and performant applications. With the advent of AJAX, we can asynchronously load the entire application in parts.

网络已经从一堆静态HTML页面演变为可靠,交互式和高性能的应用程序。 随着AJAX的问世,我们可以分批异步加载整个应用程序。

Whenever there is a change in any part of the application due to real-time updates or user input, that part only is loaded asynchronously to reflect the updated state. This means that only the respective Document Object Model (DOM) container should be updated to reflect the changes to the client.

每当应用程序的任何部分由于实时更新或用户输入而发生更改时,该部分仅被异步加载以反映更新的状态。 这意味着仅应更新相应的文档对象模型( DOM )容器以将更改反映到客户端。

For example, consider the comments section on Facebook. The comments data fetched on initial load is appended to the DOM. Now, when you add a new comment, it makes an asynchronous request to the server to save this comment in the database, and update the DOM to reflect the current state.

例如,考虑Facebook上的评论部分。 初始加载时获取的注释数据将附加到DOM。 现在,当您添加新注释时,它将向服务器发出异步请求,以将该注释保存在数据库中,并更新DOM以反映当前状态。

Let’s get into the details of this example and understand how that would work. Let’s say that I have 20 comments in my comments array. The comments array is the source of truth, and it reflects the current state at any point in time. When the user adds a new comment, we need to modify this comments’ array once the new comment has been successfully added to the database. The comments array now holds 21 comments.

让我们进入这个例子的细节,并理解它是如何工作的。 假设我的评论数组中有20条评论。 评论数组是事实的来源,它反映了任何时间点的当前状态。 当用户添加新评论时,一旦新评论成功添加到数据库中,我们就需要修改此评论的数组。 注释数组现在包含21条注释。

Oh yeah, we also need to write code to update the DOM to reflect the current state (Assume we’re using Vanilla JavaScript or jQuery here. Cool stuff coming up next!). This means that the comments DOM container is subscribed to the comments array. It should be modified when there is any change in the comments array. We can safely say that the comments array is the model here, and the comments container is the view.

哦,是的,我们还需要编写代码来更新DOM以反映当前状态(假设我们在这里使用Vanilla JavaScript或jQuery。接下来会出现很酷的事情!)。 这意味着注释DOM容器已订阅了注释数组。 当注释数组有任何更改时,应对其进行修改。 我们可以肯定地说,这里的注释数组是模型,而注释容器是视图。

Let’s add something more to this — hundreds of div elements are subscribed to this comments model, which means that we need to write code to update each of these div elements.

让我们为此添加更多内容-数百个div元素已订阅此注释模型,这意味着我们需要编写代码来更新每个div元素。

function updateCommentsSubscriber (response) {    commentsArr = [ ...response ] // commentsArr = ['Comment 1', 'Comment 2', ...]    var firstDiv = document.getElementById('first')    firstDiv.innerHTML = commentsArr.length    var secondDiv = document.getElementById('second')    secondDiv.innerHTML = commentsArr.toString()    ...}

Sigh! Imagine if this happened at the scale at which Facebook operates. Whenever we have a new element that is subscribed to that model, we’d have to write code to make changes to that element. This approach is not scalable.

叹! 想象一下,这是否发生在Facebook经营的规模上。 每当我们有一个订阅该模型的新元素时,就必须编写代码来对该元素进行更改。 这种方法是不可扩展的。

Facebook dealt with the scalability and DOM slowness issue by building a library called React. React was first deployed on the Newsfeed section of Facebook in 2011, and then on Instagram in 2012. It was open-sourced in 2013 and has been applauded by the community worldwide ever since.

Facebook通过构建一个名为React的库来解决可伸缩性和DOM慢度问题。 React首先在2011年部署在Facebook的Newsfeed部分,然后在2012年部署在Instagram。它于2013年开源,此后一直受到全世界社区的称赞。

In this tutorial, we’ll build on the fundamentals of React. By the end of this tutorial, you should be able to write your first React app.

在本教程中,我们将基于React的基础知识。 在本教程结束时,您应该可以编写第一个React应用程序。

目录 (Table of Contents)

  1. Introducing React

    介绍React
  2. JSX

    JSX
  3. ES6

    ES6
  4. React Elements

    React元素
  5. Components

    组件
  6. State & Props

    状态与道具
  7. Stateless Components

    无状态组件
  8. Lifecycle methods

    生命周期方法
  9. Virtual DOM

    虚拟DOM
  10. Building your first React app using create-react-app

    使用create-react-app构建您的第一个React应用

While I suggest a deep dive into each of these topics, please feel free to skip any of these if you’re already confident about it.

虽然我建议深入探讨每个主题,但如果您对此有信心,请随时跳过其中的任何一个。

介绍React (Introducing React)

React is a JavaScript library used for building user interfaces. It solves the scalability issue mentioned earlier by efficiently updating the DOM.

React是一个JavaScript库,用于构建用户界面 。 它通过有效地更新DOM解决了前面提到的可伸缩性问题。

One way to update the DOM is by manually putting in values in the respective DOM nodes, which is obviously slow and not scalable.

更新DOM的一种方法是通过在相应的DOM节点中手动输入值,这显然很慢且不可扩展。

Angular solves this problem by using data-binding. It binds the variables used in the view with their respective counterparts in the model. It automatically updates all the instances of a variable in a view when its respective value in a model changes.

Angular通过使用数据绑定解决了这个问题。 它将视图中使用的变量与模型中的相应变量绑定在一起。 当模型中变量的相应值更改时,它将自动更新视图中变量的所有实例。

On the other hand, React provides a different approach to solving this problem. It uses a technique called Reconciliation to evaluate the difference in the DOM representation at two points in time. It only updates the part that is changed. This will become clear once we get into the details of how React works. For now, let’s consider a simple example:

另一方面,React提供了解决此问题的不同方法。 它使用一种称为对帐的技术来评估两个时间点DOM表示形式的差异。 它仅更新已更改的零件。 一旦我们了解了React如何工作的细节,这将变得很清楚。 现在,让我们考虑一个简单的示例:

This goes into the HTML:

这进入HTML:

Put the below code in a JavaScript file:

将以下代码放入JavaScript文件中:

class HelloReact extends React.Component {    render () {        return (            
Hello React!
) }}ReactDOM.render(, document.getElementById('app'))

The above example will print Hello React! on the screen. HelloReact is called a component in React. The render method inside this component returns the DOM representation.

上面的示例将打印Hello React! 屏幕上。 HelloReact在React中称为组件 。 该组件内部的render方法返回DOM表示形式。

It’s not a coincidence that I wrote HTML in JavaScript.

Hello React!> inside render method is a JSX syntax. It lets us write HTML in JavaScript.

我用JavaScript编写HTML并非偶然。

Hello React! > i渲染方法是 JSX语法。 它使我们可以用JavaScript编写HTML。

The last statement does the work of rendering the HelloReact component inside our app container. In the following two sections, we'll dive deeper into JSX and ES6.

最后一条语句完成了在我们的app容器内呈现HelloReact组件的工作。 在以下两个部分中,我们将更深入地研究JSX和ES6。

JSX (JSX)

If we didn’t have JSX, you’d have to write the above JSX code as:

如果我们没有JSX,则必须将上面的JSX代码编写为:

React.createElement("div", null, "Hello React!")

This can complicate things if you need to deal with nested elements.

如果您需要处理嵌套元素,这会使事情复杂化。

For example:

例如:

React.createElement("div", { className: "container" },    React.createElement("span", null, "Hello React!"),    React.createElement("span", null, "I'm inside HelloReact Component"))

And this is the JSX syntax for the above code:

这是上面代码的JSX语法:

Hello React! I'm inside HelloReact Component

Writing JSX inside a React component gives a clear idea of what the component is going to render to the DOM. It looks clean and intuitive.

在React组件中编写JSX可以清楚地知道该组件将要呈现给DOM的内容。 它看起来干净直观。

If you’re already convinced of using JSX with React, continue reading to learn more. If not, React does allow you to use it without JSX. You can learn more about it here.

如果您已经确信将JSX与React一起使用,请继续阅读以了解更多信息。 如果没有,React允许您在没有JSX的情况下使用它。 您可以在此处了解更多信息。

JSX is just a JavaScript extension that allows writing HTML-like code:

JSX只是一个JavaScript扩展,它允许编写类似HTML的代码:

Hello {name}!

The expression inside the curly braces will be evaluated to the value of the variable name. You can even call functions inside JSX:

花括号内的表达式将被计算为变量name的值。 您甚至可以在JSX内部调用函数:

Hello, {formatName('james.gosling')!}

This would call the formatName function and pass james.gosling as the parameter to it. It'll render the value that is returned from the function formatName.

这将调用formatName函数,并将james.gosling作为参数传递给它。 它将呈现从函数formatName返回的值。

条件语句 (Conditional Statements)

It is often the case that you need to render a DOM node only when a particular value has been set.

通常,只有在设置了特定值后才需要渲染DOM节点。

This can be achieved using JSX as:

这可以通过使用JSX来实现:

greetUser (userName) {    if (isUserLoggedIn) {        return 
Hello, {userName}!
} return
Hello, Guest!
}

The above example will greet a logged in user with his name and as Guest when a user is not logged in.

上面的示例将以未登录用户的身份和来宾身份欢迎已登录用户。

Please note that this conditional rendering is not similar to the show/hide scenario. Based on the value of the variable isUserLoggedIn, only one of the two elements will be rendered to the DOM at a time.

请注意,此条件渲染与显示/隐藏场景不同。 基于变量isUserLoggedIn的值,一次只能将两个元素之一呈现给DOM。

使用地图功能渲染子节点 (Rendering Child Nodes using the map function)

Let’s consider our comments example from above. Here, we have a comments array, and we need to render all of the comments in a DOM container.

让我们考虑上面的评论示例。 在这里,我们有一个comment数组,我们需要在DOM容器中呈现所有注释。

map is a native JavaScript function used for iterating the elements in an array. You can pass a custom iterator function as one of its arguments. Each of the elements in the array would be serving as input to this iterator function. map will output an array based on the values returned during each iteration.

map是一个本机JavaScript函数,用于迭代数组中的元素。 您可以将自定义迭代器函数作为其参数之一传递。 数组中的每个元素都将用作此迭代器函数的输入。 map将基于每次迭代期间返回的值输出一个数组。

map comes handy when building React components. You can learn more about it here.

当构建React组件时, map变得很方便。 您可以在此处了解更多信息。

renderComments (commentsArr) {    /* commentsArr would look similar to this structure below    commentsArr = [{        id: 1,        text: "I'm a comment!"    }]    */    return (        
{ commentsArr.map (function (comment) { return
{comment.text}
}) }
)}

The above renderComments method would return the result of the map method. In this case, map returns an array of DOM nodes.

上面的renderComments方法将返回map方法的结果。 在这种情况下, map返回DOM节点数组。

Notice the use of key with each div element. We'll get into the details of using key with DOM elements later. For now, it's just used as a way for uniquely identifying DOM elements.

注意每个div元素都使用key 。 稍后我们将详细介绍将key与DOM元素一起使用的细节。 目前,它仅用作唯一标识DOM元素的方法。

将JSX编译为JavaScript (Compiling JSX to JavaScript)

The React library doesn’t understand JSX. It’s just used to make the developer’s job easier. So, what does React do when it comes across this weird HTML-like syntax in JavaScript code?

React库不了解JSX。 它只是用来简化开发人员的工作。 那么,当JavaScript代码遇到类似HTML的怪异语法时,React会做什么?

JSX is transpiled to JavaScript statements by the Babel plugin before React encounters them. Transpilation is the process of converting one source language to another. So, all that React sees is simple JavaScript statements.

在React遇到之前, Babel插件将JSX转换为JavaScript语句。 翻译是将一种源语言转换为另一种语言的过程 。 因此,React看到的只是简单JavaScript语句。

The simple JSX code from above

上面的简单JSX代码

Hello React!

gets transpiled to

被移植到

React.createElement("div", { className: 'heading' }, "Hello React!")

createElement method is defined on React.

createElement方法是在React上定义的。

The first argument to the createElement method is the type of the DOM node that you'd like React to create for you. It can be div, span, p, and so on.

createElement方法的第一个参数是您希望React为您创建的DOM节点的类型。 它可以是divspanp等。

The second argument is used for specifying the attributes on the DOM node. In this case, we’re telling React that the className of the node is heading.

第二个参数用于指定DOM节点上的属性。 在这种情况下,我们告诉React节点的classNameheading

Notice the use of className instead of conventional class attribute. In React, class attribute is specified as className to avoid conflicts with the existing attributes.

请注意,使用className代替了常规的class属性。 在React中,将class属性指定为className以避免与现有属性冲突。

The third argument carries information about the children of the DOM node. In this case, it is just plain text that will be added as innerHTML to the DOM node

第三个参数携带有关DOM节点的子代的信息。 在这种情况下,纯文本将作为innerHTML添加到DOM节点

The createElement method is analogous to the document.createElement method in JavaScript, but it outputs a React element. We'll get into the details of React Elements later.

createElement方法类似于JavaScript中的document.createElement方法,但是它输出React元素。 稍后我们将详细介绍React Elements。

ES6 (ES6)

ES6 is the abbreviation for ECMAScript 6 or ECMAScript 2015. In this part, we’ll learn some common ES6 techniques that make developing React components an easier task.

ES6是ECMAScript 6或ECMAScript 2015的缩写。在这一部分中,我们将学习一些通用的ES6技术,这些技术使开发React组件变得更加容易。

letconst (let & const)

let is used for declaring block-level variables, and const is used for declaring constants. JavaScript follows a function-level scoping.

let用于声明块级变量,而const用于声明常量。 JavaScript遵循功能级作用域

A variable declared inside a function can be used in the entire function, but not outside of it.

在函数内部声明的变量可以在整个函数中使用,但不能在其外部使用。

Let’s consider an example that will help us understand function-level scoping:

让我们考虑一个示例,该示例将帮助我们理解函数级作用域:

function pokemon (id) { //id = 12    if (id === 12) {        var pokemonObj = {            id: 12,            name: 'butterfree',            height: 11,            weight: 22,            abilities: [                {                    name: 'tinted-lens'                }            ]        }    }    return pokemonObj    }

The above pokemon method takes id as the parameter, and returns pokemonObj if the id is equal to 12. Go ahead and run this function in your browser console.

上面的pokemon方法将id作为参数,如果id等于12 ,则返回pokemonObj 。 继续并在浏览器控制台中运行此功能。

If you execute pokemon(12), it prints the pokemonObj as expected. However, if you execute pokemon(13), it doesn't display an error, and instead prints undefined.

如果执行pokemon(12) ,它将按预期打印pokemonObj 。 但是,如果执行pokemon(13) ,则不会显示错误,而是显示undefined

Notice that pokemonObj gets defined in the if construct, which means if the id is not equal to 12, pokemonObj should not be available in the context of the pokemon function.

注意, pokemonObj是在if构造中定义的,这意味着如果id不等于12,则pokemonObjpokemon函数的上下文中不可用。

JavaScript follows function-level scoping, which means a variable declared in any statement inside a function is available throughout the function. So, pokemonObj is available even if it is declared inside if block.

JavaScript遵循函数级作用域,这意味着在函数内部的任何语句中声明的变量在整个函数中都可用。 因此,即使在if块中声明了pokemonObjpokemonObj仍然可用。

The let construct solves this problem as it lets us limit the scope of variables to block level.

let构造解决了这个问题,因为它允许我们将变量的范围限制为块级别。

Use let for declaring the pokemonObj and check the results:

使用let声明pokemonObj并检查结果:

function pokemon (id) { //id = 12    if (id === 12) {        let pokemonObj = {            id: 12,            name: 'butterfree',            height: 11,            weight: 22,            abilities: [                {                    name: 'tinted-lens'                }            ]        }    }    return pokemonObj    }

You’ll get pokemonObj is not defined, and that justifies the block-level scoping of variables declared using the let construct.

您将获得pokemonObj is not defined ,并证明使用let结构声明的变量的块级作用域是合理的。

A variable declared using const cannot be modified:

使用const声明的变量不能被修改:

const POKEMON = 'butterfree' pokemon = 'pikachu'

The second statement above displays an error since it’s not allowed to modify constant variables.

上面的第二条语句显示错误,因为不允许修改常量变量。

对象分解 (Object Destructuring)

Consider an object, berries, which are small fruit that can provide HP and status condition restoration, stat enhancement, and even damage negation when eaten by the Pokémon:

考虑一个物体, berriesberries是一种小水果,当被神奇宝贝吃掉时,可以提供生命力和状态恢复,状态增强,甚至可以消除伤害:

var berries = {    id: 1,    name: 'cheri',    growth_time: '3',    max_harvest: 5,    natural_gift_power: 60,    size: 20,    smoothness: 25,    soil_dryness: 15,    natural_gift_type: {        name: 'fire',        url: 'https://pokeapi.co/api/v2/type/10/'    }}

If I need to use some of the keys from the above object, the conventional approach is:

如果需要使用上述对象中的某些键,则常规方法是:

var id = berries.idvar name = berries.namevar growthTime = berries.growth_time

And with ES6:

对于ES6:

let { id, name, growth_time, max_harvest, natural_gift_power, size } = berries

The above statement creates local variables as id, name, growth_time, max_harvest, natural_gift_power, and size, and each of them will have the value corresponding to that in the berries object. Isn't that cool?

上面的语句创建了局部变量,如idnamegrowth_timemax_harvestnatural_gift_powersize ,并且每个变量的值都与berries对象中的值相对应。 那不是很酷吗?

Here, we’re destructuring the object to refer individual keys. If any of the keys wasn’t defined in the object, its value would be undefined.

在这里,我们要解构该对象以引用各个键。 如果未在对象中定义任何键,则其值将为undefined

字符串模板 (String Templating)

Here’s the old way of concatenating strings in JavaScript:

这是在JavaScript中串联字符串的旧方法:

var cheriDescription = "One of the berries is " + name + ". Its growth time is " + growth_time + ". Its size is " + size + ". Its Max Harvest is " + max_harvest.

And here is the ES6 way:

这是ES6的方式:

let cheriDescription = `One of the berries is ${name}. Its growth time is ${growth_time}. Its size is ${size}. Its Max Harvest is ${max_harvest}.`

You can write the entire sentence in backticks without having to concatenate static text and variables in parts. Wrap the variables inside '${}'. This looks a lot cleaner.

您可以将整个句子写在反引号中,而不必将静态文本和变量分成多个部分。 将变量包装在'${}' 。 这看起来更干净。

箭头功能 (Arrow Functions)

This one’s my favorite. Below is the old way of writing functions in JavaScript:

这是我的最爱。 下面是用JavaScript编写函数的旧方法:

function getBerrySize (berries) {    return berries.size}

And this is the ES6 way of writing functions:

这是ES6编写函数的方式:

const getBerrySize = (berries) => berries.size

Arrow functions follow this syntax:

箭头函数遵循以下语法:

declaration functionName = (functionParams) => return result

declaration functionName = (functionParams) =&g t; return res t; return res结果

The above function getBerrySize returns the size of the berry. Notice that we didn't write the word return in the above arrow function. Use of return is optional if the body of the arrow function has just one statement and it returns that statement.

上面的函数getBerrySize返回berry的大小。 注意,我们没有在上面的箭头函数中写出单词return 。 如果arrow函数的主体只有一个语句,并且返回该语句,则使用return是可选的。

If a function body has more than one statement, wrap them in curly braces.

如果函数主体具有多个语句,则将它们括在花括号中。

Arrow functions behave a little different compared to normal functions when used with the this construct. Learn more about this and how the arrow functions behave differently when used with this from my article here.

this结构一起使用时,箭头函数的行为与普通函数相比略有不同。 了解更多关于this ,以及如何与使用时的箭头功能表现不同this从我的文章在这里 。

班级 (Classes)

With ES6, we can wrap the relevant functions used for implementing a particular functionality inside a class.

使用ES6,我们可以将用于实现特定功能的相关功能包装在类中。

Let’s build a class to evaluate berries:

让我们建立一个评估浆果的类:

class Berries {    constructor (berries) {        this.berries = berries    }    getSize () {        return this.berries.size    }    getGrowthTime () {        return this.berries.growth_time    }}const cherries = new Berries(berries)cherries.getSize() // 20cherries.getGrowthTime() // 3

We’ve wrapped the relevant berries methods inside the class Berries.

我们已经在Berries类中包装了相关的berries方法。

The statement const cherries = new Berries(berries) instantiates the Berries class and create an Object of type Berries.

语句const cherries = new Berries(berries)实例化Berries类并创建Berries类型的Object。

The input passed to the Berries constructor is the berries object we've created earlier. We can use methods defined in the Berries class on this object.

传递给Berries构造函数的输入是我们之前创建的berries对象。 我们可以在此对象的Berries类中使用定义的方法。

Now that we’ve learned most of the common ES6 techniques, we can use them in the following sections.

现在,我们已经学习了大多数常见的ES6技术,可以在以下各节中使用它们。

React元素 (React Elements)

React Elements are the smallest units that represent the state of the DOM at any point in time.

React Elements是表示任何时间点DOM状态的最小单位。

The browser doesn’t understand React. Like we saw earlier, JSX is converted to JavaScript statements for creating a DOM node.

浏览器不了解React。 如我们先前所见,JSX被转换为JavaScript语句以创建DOM节点。

With this statement:

带有以下语句:

React.createElement("div", { className: 'heading' }, "Hello React!")

The div DOM node isn't yet appended to the DOM. The above statement is converted to plain JavaScript object as:

div DOM节点尚未附加到DOM。 上面的语句转换为普通JavaScript对象,如下所示:

{    type: 'div',    props: {        className: 'heading',        children: 'Hello React!'    }}

These objects are called React Elements.

这些对象称为React Elements

They contain two important keys:

它们包含两个重要的键:

type specifies the type of the DOM node. It can be div, span, p, and so on.

type指定DOM节点的类型。 它可以是divspanp等。

props describes the properties of that element. In this case, we have className and children.

props描述了该元素的属性。 在这种情况下,我们有classNamechildren

The nested elements can be specified as the value of the children key.

可以将嵌套元素指定为children项键的值。

ReactDOM does the work of converting these React Elements to actual DOM nodes and also updates them accordingly.

ReactDOM完成将这些React Elements转换为实际DOM节点的工作,并相应地对其进行更新。

React elements are immutable and are cheap to create. If there is any change in a React Element, its older instance is destroyed, and a newer one is created from scratch.

React元素是不可变的,而且创建起来很便宜。 如果React Element中有任何更改,它将销毁其较旧的实例,并从头开始创建一个较新的实例。

However, the corresponding DOM node is not always destroyed to make room for a newer one. DOM operations are expensive, and hence they should be avoided at all possible instances.

但是,并不总是销毁相应的DOM节点以为新的节点腾出空间。 DOM操作非常昂贵,因此在所有可能的情况下都应避免使用它们。

ReactDOM does a great job here. It creates new React elements because creating them is cheap, however, it efficiently updates only the part of the real DOM node that is modified.

ReactDOM在这里做得很好。 它创建新的React元素是因为创建它们很便宜,但是它仅有效地更新了实际DOM节点中已修改的部分。

React uses a diffing algorithm to find out what needs to be updated to the DOM. We’ll learn more about it in the Virtual DOM section.

React使用差异算法来找出需要更新到DOM的内容。 我们将在“虚拟DOM”部分中了解更多信息。

Let’s go through what we’ve learned so far:

让我们回顾一下到目前为止所学到的内容:

  • JSX is an HTML-like syntax that is used in React components. It’s just a representation of the DOM node and doesn’t actually append elements to the DOM.

    JSX是在React组件中使用的类似HTML的语法。 它只是DOM节点的表示,实际上并没有将元素附加到DOM。

  • The Babel plugin transpiles it to plain JavaScript statements as React.createElement.

    Babel插件将其作为React.createElement为普通JavaScript语句。

  • The React.createElement statements are further converted into JavaScript objects.

    React.createElement语句进一步转换为JavaScript对象。

  • ReactDOM efficiently updates the real DOM using the objects created above.

    ReactDOM使用上面创建的对象有效地更新实际DOM。

组件 (Components)

Components are reusable classes that define a particular functionality. React follows a component-based structure. Each of the components that we define in React extends the basic functionalities of the native React Component.

组件是定义特定功能的可重用类。 React遵循基于组件的结构。 我们在React中定义的每个组件都扩展了本地React组件的基本功能。

Let’s create a simple React component for input text:

让我们为输入文本创建一个简单的React组件:

class Text extends React.Component {    state = {        value: ''    }    onChange = (e) => {        this.setState({ value: e.target.value })    }    render () {        return (                    )    }}export default Text

Each of the React components has an implementation of the render method. This method returns the DOM representation for that component. In our case, it returns an input element. Remember, this input element is not actually a DOM node. It's just a DOM representation.

每个React组件都有一个render方法的实现。 此方法返回该组件的DOM表示形式。 在我们的例子中,它返回一个input元素。 请记住,此input元素实际上不是DOM节点。 这只是DOM表示。

The attributes — text, onChange and value that are passed to the input element are called props in React. onChange is an event handler that gets called whenever the value of the text in input box changes. props in React are read-only.

传递给input元素的属性( textonChangevalue在React中称为propsonChange是一个事件处理程序,只要输入框中的文本值发生更改,就会调用该事件处理程序。 React中的props是只读的。

React components maintain an internal state for handling the complexity based on various parameters. At the beginning of our component, we’ve initialized an object called state. This state variable handles the state of the Text Component. The state can be modified using the setState method, as shown in the onChange method defined above.

React组件维护一个内部状态以根据各种参数处理复杂性。 在组件的开头,我们初始化了一个名为state的对象。 此状态变量处理文本组件的状态。 可以使用setState方法修改状态,如上面定义的onChange方法所示。

The Text component is an individual unit. It gets interesting when these components can be directly used in other complicated components. React follows a Composition based model, which means importing smaller components to implement complex functionality. It composites different smaller components into a bigger component to make up for a working feature.

Text组件是一个单独的单元。 这些组件可以直接在其他复杂组件中使用时,会变得很有趣。 React遵循基于Composition的模型,这意味着导入较小的组件以实现复杂的功能。 它将不同的较小组件组合为一个较大的组件,以弥补工作中的功能。

Let’s create a forms component that would import the Text component from above:

让我们创建一个表单组件,该组件将从上方导入Text组件:

import Text from './text'class Forms extends React.Component {    state = {}    render () {        return (            

Form for basic details

) }}

First, we’re importing the Text component. Notice how the Text component is included in the render method of the Forms component.

首先,我们要导入文本组件。 请注意,Text组件如何包含在Forms组件的render方法中。

When the Forms component is rendered, the /> gets replaced by the return value of the render method in the Text component.

当窗体部件被呈现时, />得到由返回值替换ö f the呈现的文本组件方法。

有关stateprops更多信息 (More on state and props)

As mentioned earlier, React follows a Composition-based model. The bigger components can customize the components that are to be imported by sending in related props.

如前所述,React遵循基于组合的模型。 较大的组件可以通过发送相关道具来自定义要导入的组件。

Let’s modify the render method of the above Forms component as

让我们将上述Forms组件的render方法修改为

render () {    return (        

Form for basic details

;
)}

Notice how we’re passing type props in the Text component.

注意我们如何在Text组件中传递type属性。

We need to make changes to our Text component to accept these props.

我们需要对Text组件进行更改以接受这些道具。

Check out the changes in the render method:

查看render方法中的更改:

render () {    let { type } = this.props    return (            )}

The props passed by the Forms component are available as an object in the Text Component. Notice how we're using the type property in the Text component that was passed by the forms component.

Forms组件传递的props可以作为Text组件中的对象使用。 请注意,我们如何在Forms组件传递的Text组件中使用type属性。

The state variable manages the internal state of a component. It can be changed based on Network changes, user’s input or any scheduled updates.

状态变量管理组件的内部状态。 可以根据网络更改,用户输入或任何计划的更新来更改它。

state is nothing but a JavaScript object. It can be changed using the setState method. The setState method takes an object as an input. Whenever any value changes in a state, we only pass that value in the setState method instead of passing the entire state object.

state不过是一个JavaScript对象。 可以使用setState方法更改它。 setState方法将一个对象作为输入。 每当状态中的任何值发生变化时,我们仅在setState方法中传递该值,而不传递整个状态对象。

Let’s say that we have our Berries Component and that its internal state is the berries object that we defined above.

假设我们有浆果组件,其内部状态是上面定义的berries对象。

If there's a change in the growth_time property of the berries object, we can update it in the state as:

如果berries对象的growth_time属性发生变化,我们可以将状态更新为:

this.setState({ growth_time: new_growth_time })

We’re not passing the entire berries object to the setState method. We're only passing the value that needs to be updated.

我们没有将整个berries对象传递给setState方法。 我们只是传递需要更新的值。

The setState method operates as an asynchronous function. Multiple state update calls are batched and invoked together at later intervals to deal with performance issues.

setState方法用作异步函数。 批处理多个状态更新调用,并在以后的时间间隔一起调用它们,以处理性能问题。

无状态组件 (Stateless Components)

The components defined above had their own state in place. However, we can also define Stateless components.

上面定义的组件具有自己的状态。 但是,我们也可以定义无状态组件。

These components are pure functions. They don’t modify the input passed to them. These are just representational components.

这些组件是纯函数。 他们不修改传递给他们的输入。 这些只是代表性的组成部分。

Let’s see an example of a stateless component:

让我们看一个无状态组件的示例:

const getBerrySize = (props) => {    let { size } = props    return (        

{size}<;/p> )}

The only job of this component is to return a DOM representation for displaying the size of the Berries.

该组件的唯一工作是返回DOM表示形式以显示浆果的大小。

组件生命周期 (Component Lifecycle)

A React Component follows a certain lifecycle pattern. It goes through four important phases:

React组件遵循一定的生命周期模式。 它经历了四个重要阶段:

  1. Initialization

    初始化
  2. Mounting

    安装
  3. Updating

    更新中
  4. Unmounting

    正在卸载

Let’s look into some of the methods that are invoked during these phases

让我们看一下在这些阶段中调用的一些方法

InitializationInitialize state and props.

初始化初始化状态和道具。

MountingcomponentWillMount— this method is invoked just before the mounting occurs. It is called before the render method. For setting the initial state & props, it’s recommended to use the constructor in place of this method.

Mounting componentWillMount挂载发生前立即调用此方法。 在render方法之前调用它。 为了设置初始状态和道具,建议使用constructor代替此方法。

render — this is the only required method in a class component. It returns the DOM representation at any point in time. It examines the value of state and props, and returns the updated DOM representation.

render —这是类组件中唯一需要的方法。 它在任何时间点返回DOM表示。 它检查stateprops的值,并返回更新的DOM表示形式。

componentDidMount — this method gets invoked immediately after the component is mounted. This is a good place to instantiate network requests to the server. Once the data is loaded from the server, you can call setState method to invoke render for updating the DOM nodes.

componentDidMount —挂载组件后立即调用此方法。 这是实例化对服务器的网络请求的好地方。 从服务器加载数据后,就可以调用setState方法来调用render来更新DOM节点。

UpdatingcomponentWillReceiveProps — if there is any change in props, this method is called to render the updated state. It’s not recommended to use this method from React version 16 on.

更新 componentWillReceiveProps —如果props有任何更改,则调用此方法以呈现更新的状态。 不建议从React版本16开始使用此方法。

shouldComponentUpdate — if this method returns true, render method is called to make room for the updated state and props.

shouldComponentUpdate -如果该方法返回truerender方法被调用,以腾出空间更新的stateprops

componentWillUpdate — this method gets called immediately before render begins doing its work.

componentWillUpdate —在渲染开始工作之前立即调用此方法。

componentDidUpdate — this method gets called once the updated state is rendered to the DOM.

componentDidUpdate —将更新的状态呈现给DOM后,将调用此方法。

UnmountingcomponentWillUnmount — this method is invoked just before the unmounting of a component. This is a good place to remove any subscriptions from the component.

Unmounting componentWillUnmount —刚好在卸载组件之前调用此方法。 这是从组件中删除所有订阅的好地方。

This is a brief overview of the React Component Lifecycle. I’ll explain these methods in detail in my future articles.

这是React组件生命周期的简要概述。 我将在以后的文章中详细解释这些方法。

虚拟DOM (Virtual DOM)

I mentioned the scalability problem earlier while introducing React. In this section, we’ll see how React efficiently solves this problem.

我在介绍React时提到了可扩展性问题。 在本节中,我们将看到React如何有效地解决这个问题。

From what you’ve learned so far, it’s clear that React doesn’t directly update the real DOM. All React knows is that DOM is nothing but a JavaScript object. This giant JavaScript object is called Virtual DOM.

从到目前为止所学的知识来看,很明显React不会直接更新真实的DOM。 React只知道DOM只是一个JavaScript对象。 这个巨大JavaScript对象称为Virtual DOM

If there is any change in the output of the render method in any of the components, the Virtual DOM accommodates these changes by destroying its older instance, and creating a newer one.

如果任何组件中render方法的输出有任何更改,则虚拟DOM会通过销毁其旧实例并创建一个新实例来适应这些更改。

As mentioned earlier, React uses a technique called Reconciliation to evaluate the difference between the Real DOM and the Virtual DOM.

如前所述,React使用一种称为对帐的技术来评估实际DOM和虚拟DOM之间的差异。

Reconciliation is the action of making one view or belief compatible with another. And that’s exactly what ReactDOM does. It makes changes to the real DOM to make it compatible with the current state of the virtual DOM. React uses a diffing algorithm to evaluate the changes that are to be made to the real DOM.

和解是使一种观点或信念与另一种观点兼容的行为 。 而这正是ReactDOM所做的。 它对真实DOM进行更改,以使其与虚拟DOM的当前状态兼容。 React使用差异算法来评估要对真实DOM进行的更改。

It uses a heuristic algorithm that is based on two assumptions:

它使用基于两个假设的启发式算法:

  1. Two elements of different types will produce different trees

    不同类型的两个元素将产生不同的树
  2. The Stable elements, or the elements that are not modified, are identified using a unique identifier called key.

    使用称为key的唯一标识符来标识Stable元素或未修改的元素。

不同类型的元素 (Elements of different types)

React first compares the type of the root element. If the type of root element is different in the real DOM and the virtual DOM, it destroys the real DOM and creates a new one.

React首先比较根元素的类型。 如果实际DOM和虚拟DOM中根元素的类型不同,则会破坏实际DOM并创建一个新的DOM。

For example, if the root type in real DOM was div, and the one in virtual DOM was span, the diffing algorithm would erase the entire div container from the real DOM.

例如,如果实际DOM中的根类型为div ,而虚拟DOM中的根类型为span ,则差异算法将从实际DOM中删除整个div容器。

相同类型的DOM元素 (DOM Elements of the same type)

This case deals with elements that are of the same type, but that have some differences in their property values.

这种情况处理的是相同类型的元素,但其属性值有所不同。

Consider this DOM node in real DOM:

考虑真实DOM中的此DOM节点:

React Diffing Algorithm

Now, consider the updated DOM node which is the output of a render method of some Component:

现在,考虑更新的DOM节点,它是某些Component的render方法的输出:

React Diffing Algorithm

By comparing both of these nodes, React would know that only the className of the nodes is changed, and it would efficiently update just the value of the class in the real DOM.

通过比较这两个节点,React将知道仅节点的className被更改,并且它将有效地更新实际DOM中的类的值。

确定子代在父容器中的位置 (Identifying the position of Children in the parent container)

React recommends the use of the key prop if similar children are to be appended to a particular DOM node.

如果要将相似的子项附加到特定的DOM节点,React建议使用key prop。

Let’s consider the example of a comments array:

让我们考虑一个注释数组的示例:

commentsArr.map (comment => {    return 
{comment.text}
})

The use of key in the child nodes of the comments container helps React to uniquely identify different comment nodes. If there is a change in any of the comment nodes, React would know which one to update based on the value of the key.

在注释容器的子节点中使用key有助于React唯一地标识不同的注释节点。 如果任何一个注释节点发生变化,React都会根据键的值知道要更新哪个。

使用create-react-app进行React入门 (Getting Started with React using create-react-app)

create-react-app is a React Command Line interface tool that is used for creating the initial boilerplate for any react application.

create-react-app是一个React命令行界面工具,用于为任何React create-react-app创建初始样板。

It does the tedious job of setting up a development server, handling the compilation of JSX down to JavaScript as discussed earlier, and it does a few more things.

如前所述,它完成了设置开发服务器,处理JSX到JavaScript的繁琐工作,并且还做了其他一些事情。

npm i create-react-app -g

This installs the create-react-app node module globally on your system.

这将在系统上全局安装create-react-app节点模块。

The command create-react-app my-app creates a react project inside themy-app directory. Play around with the files and try building a smaller React component.

命令create-react-app my-appmy-app目录中创建一个react项目。 试一试这些文件,然后尝试构建一个较小的React组件。

I hope you now have an idea of what React is and how to use it.

我希望您现在对React是什么以及如何使用它有所了解。

让我们回顾一下到目前为止所学到的东西 (Let’s recap what we’ve learned so far)

  1. We saw that updating DOM nodes using raw JavaScript code is not scalable.

    我们看到使用原始JavaScript代码更新DOM节点是不可扩展的。
  2. React is a JavaScript library for building user interfaces. It solves the scalability issue by efficiently updating the DOM.

    React是一个用于构建用户界面JavaScript库。 它通过有效地更新DOM解决了可伸缩性问题。
  3. React components output DOM representation in the form of JSX. JSX is just syntactic sugar that is used to ease the development work. It gets transpiled to JavaScript statements in the form of React.createElement.

    React组件以JSX的形式输出DOM表示形式。 JSX只是语法糖,用于简化开发工作。 它得到transpiled在形式JavaScript语句React.createElement

  4. We learned about most of the common ES6 techniques like the use of let and const, Object Destructuring, Classes, Arrow Functions, and String Templating. These are used while writing React components.

    我们了解了大多数常见的ES6技术,例如letconst的使用,对象解构,类,箭头函数和字符串模板化。 这些在编写React组件时使用。

  5. We learned about React Elements and how they are created.

    我们了解了React Elements及其创建方式。
  6. We learned that React follows a component-based pattern and how it uses Composition to create complex components using simpler ones. The Component uses state and props for handling internal state.

    我们了解到,React遵循基于组件的模式,以及它如何使用Composition来使用简单的组件创建复杂的组件。 组件使用stateprops来处理内部状态。

  7. We took a deep dive into how React creates Virtual DOM and also understood the underlying diffing algorithm that is used for efficiently updating the real DOM.

    我们深入研究了React如何创建虚拟DOM,并了解了用于有效更新实际DOM的底层差异算法。

In the next series of articles on React, I’ll cover the following topics in more detail:

在关于React的下一系列文章中,我将更详细地介绍以下主题:

  1. The lifecycle of React Components

    React组件的生命周期
  2. Virtual DOM

    虚拟DOM
  3. Getting started with React using create-react-app

    使用create-react-app开始使用React

Originally published at hashnode.com.

最初发布在hashnode.com上 。

翻译自: https://www.freecodecamp.org/news/a-beginners-guide-to-getting-started-with-react-c7f34354279e/

你可能感兴趣的:(python,javascript,java,vue,编程语言,ViewUI)