编写react组件_如何编写第一个React.js组件

 2023-09-06 阅读 16 评论 0

摘要:编写react组件 React的函数和类组件,道具,状态和事件处理程序 (React’s function and class components, props, state, and event handlers) Update: This article is now part of my book “React.js Beyond The Basics”. 更新:本文现在是我的书《超

编写react组件

React的函数和类组件,道具,状态和事件处理程序 (React’s function and class components, props, state, and event handlers)

Update: This article is now part of my book “React.js Beyond The Basics”.

更新:本文现在是我的书《超越基础的React.js》的一部分。

Read the updated version of this content and more about React at jscomplete.com/react-beyond-basics.

jscomplete.com/react-beyond-basics中阅读此内容的更新版本以及有关React的更多信息

The most important concept to understand in React.js is the component. A React component can be one of two types. It can be either a function component or a class component. Sometimes you will hear different terms to describe these two types, like stateless and stateful. Function components are also often associated with the presentational concept. I will refer to them in this article as function components and class components.

在React.js中最重要的概念是组件。 React组件可以是两种类型之一。 它可以是函数组件或组件。 有时您会听到描述这两种类型的不同术语,例如无状态有状态 。 功能组件通常也与表示概念相关联。 在本文中,我将它们称为函数组件和类组件。

A function component is the simplest form of a React component. It is a simple function with a simple contract:

功能组件是React组件的最简单形式。 这是一个具有简单合约的简单功能:

The function component receives an object of properties which is usually named props. It returns what looks like HTML, but is really a special JavaScript syntax called JSX.

函数组件接收一个通常称为props的属性对象 它返回看起来像HTML的东西,但实际上是称为JSX的特殊JavaScript语法。

A class component is a more featured way to define a React component. It also acts like a function that receives props, but that function also considers a private internal state as additional input that controls the returned JSX.

类组件是定义React组件的一种更有特色的方式。 它也像接收道具的函数一样工作,但是该函数还将私有内部状态视为控制返回的JSX的附加输入。

This private internal state is what gives React its reactive nature. When the state of a class component changes, React will re-render that component in the browser.

这种私有的内部状态使React具有React性。 当一个类组件的状态改变时,React将在浏览器中重新渲染该组件。

The State and Props objects have one important difference. Inside a class component, the State object can be changed while the Props object represents fixed values. Class components can only change their internal state, not their properties. This is a core idea to understand in React and this article will have an example of that.

State和Props对象具有一个重要区别。 在类组件内部,可以更改State对象,而Props对象则表示固定值。 类组件只能更改其内部状态,不能更改其属性。 这是React中要理解的核心思想,本文将提供一个示例。

Let’s look at an actual example of a component. A very simple one, without any input and with a simple h1 in a div output.

让我们看一下组件的实际示例。 一个非常简单的示例,没有任何输入,并且在div输出中带有简单的h1

On the left side, the component is written in the special JSX syntax.

在左侧,该组件使用特殊的JSX语法编写。

JSX allows us to describe our User Interfaces (UIs) in a syntax very close to the HTML that we are used to. It is, however, optional. React can be used without JSX, as you can see on the right side. In fact, React just compiles the JSX you see on the left to the pure JavaScript you see on the right. Then it works with compiled JavaScript in the browser.

JSX允许我们以非常类似于我们惯用HTML的语法来描述用户界面(UI)。 但是,它是可选的。 如右侧所示,React可以不使用JSX而使用。 实际上,React只是将您在左侧看到的JSX编译为您在右侧看到的纯JavaScript。 然后,它可以与浏览器中的已编译JavaScript一起使用。

The React.createElement call on the right side is a JavaScript representation of the Document Object Model (DOM). React efficiently translates it into DOM operations that it performs in the browser.

右侧的React.createElement调用是文档对象模型( DOM )JavaScript表示。 React有效地将其转换为它在浏览器中执行的DOM操作。

让我们编写一个React组件。 (Let’s write a React component.)

I will be using jsComplete’s React Playground for the examples in this article. It’s a tool where you can test your JavaScript and React code right in the browser. There is no need to install or configure anything.

我将在本文的示例中使用jsComplete的React Playground 。 它是一个可以在浏览器中测试JavaScript和React代码的工具。 无需安装或配置任何东西。

The tool has a simple two-panels interface. The left panel is the editor where you write your JavaScript and React code. The latest version of both React and ReactDOM are already pre-loaded there. The editor also understands the JSX extension and all the modern features in JavaScript. This will allow us to focus on the React API itself rather than configuring and compiling a React application.

该工具具有一个简单的两面板界面。 左侧面板是编辑器,您可以在其中编写JavaScript和React代码。 React和ReactDOM的最新版本已经预载在那里。 编辑器还了解JSX扩展以及JavaScript中的所有现代功能。 这将使我们能够专注于React API本身,而不是配置和编译React应用程序。

The right panel is the preview panel. You have a pre-defined mountNode element in the editor. When you execute your JavaScript code, anything you put in the mountNode element shows up in the preview panel. The preview panel will also show any errors you encounter when you execute your code. The playground is also a simple JavaScript REPL (Run, Eval, Print, Loop) where you can test quick JavaScript functions and expressions. To execute the code at any time press CTRL+Enter.

右侧面板是预览面板。 您在编辑器中有一个预定义的mountNode元素。 当您执行JavaScript代码时,您在mountNode元素中放置的mountNode内容都会显示在预览面板中。 预览面板还将显示您在执行代码时遇到的任何错误。 游乐场也是一个简单JavaScript REPL (运行,评估,打印,循环),您可以在其中测试快速JavaScript函数和表达式。 要随时执行代码,请按CTRL+Enter

Try the following in the REPL, for example:

例如,在REPL中尝试以下操作:

mountNode.innerHTML = 'Hello!!';

Or the simple REPL mode

还是简单的REPL模式

3 == '3'

To create a React component, define a new function. Let’s make that function return an HTML button element:

要创建一个React组件,请定义一个新函数。 让我们让该函数返回一个HTML按钮元素:

function Button() {  return (    <button>Go</button>  );}

What we returned here looks like HTML but remember that it is not. It is going to be compiled into JavaScript. The actual JavaScript that the browser sees when we use this button element in JSX is a call to the React.createElement function:

我们在这里返回的内容看起来像HTML,但请记住不是。 它将被编译成JavaScript。 当我们在JSX中使用此按钮元素时,浏览器看到的实际JavaScript是对React.createElement函数的调用:

function Button() {  return (    React.createElement("button", null, "Go")  );}

While you can use React this way without JSX, it would be a lot harder to code and maintain. So, let’s stick with JSX.

尽管您可以在没有JSX的情况下以这种方式使用React,但是编码和维护起来会更加困难。 因此,让我们坚持使用JSX。

The function above is a complete and very simple React component. Let’s use it!

上面的函数是一个完整且非常简单的React组件。 让我们使用它!

We use a component by mounting it in the browser. The function designed to do that is ReactDOM.render, which takes in two arguments:

我们通过将组件安装在浏览器中来使用它。 ReactDOM.render目的设计的函数是ReactDOM.render ,它ReactDOM.render两个参数:

  • The first is the component to render, in our case it is Button.

    第一个是要渲染的组件,在我们的例子中是Button

  • The second argument is the element in which this component should be rendered. In the REPL’s environment we can use the special mountNode variable.

    第二个参数是应在其中呈现此组件的元素。 在REPL的环境中,我们可以使用特殊的mountNode变量。

ReactDOM.render(<Button />, mountNode);

All code examples in this article have a link in the screenshot caption where you can edit the example at jsComplete REPL.

本文中的所有代码示例在屏幕截图标题中均具有一个链接,您可以在其中通过jsComplete REPL编辑该示例。

A React function component receives as its first argument the props object. This argument allows us to make the component re-usable. For example, instead of hard-coding the “Go” label of the button above, we can pass the Button component a label attribute, like we do with regular HTML elements:

React函数组件将props对象作为其第一个参数。 这个参数允许我们使组件可重用。 例如,我们可以像常规HTML元素一样,为Button组件传递label属性,而不是对上面按钮的“ Go”标签进行硬编码:

ReactDOM.render(<Button label="Save" />, mountNode);

Then we can access this attribute inside the component with a curly bracket for props.label.

然后,我们可以在组件内部使用props.label大括号访问此属性。

function Button(props) {  return (    <button>{props.label}</button>  );}

The props argument is an object that holds all the values that were passed to the component when it was rendered.

props参数是一个对象,其中包含渲染时传递给组件的所有值。

使组件具有交互性 (Making the component interactive)

We have a button element and it is rendered through a React component.

我们有一个button元素,它是通过React组件呈现的。

Let’s now add some interactivity to this so-far boring example. Let’s make that button element increment a counter value on every click and display that value as the button label itself. So the label of this button is going to start with the number 1 and when the user clicks the button its label will change to 2, 3, 4 and so on.

现在,让我们向这个无聊的示例添加一些交互性。 让我们使按钮元素在每次单击时增加一个计数器值,并将该值显示为按钮标签本身。 因此,此按钮的标签将以数字1开头,当用户单击该按钮时,其标签将更改为2、3、4,依此类推。

Since this is something that needs to be reflected in the component rendered output, it belongs to the state of the component. We need the component to re-render itself every time the counter changes. We cannot use a property here because a component props cannot be changed. By using the special React state object, we will be utilizing React’s reactive nature and we will not need to worry about how to take the changes to the browser. React will do that for us.

由于这需要在组件渲染的输出中反映出来,因此它属于组件的状态。 每当计数器改变时,我们需要组件重新呈现自身。 我们无法在此处使用属性,因为无法更改组件属性。 通过使用特殊的React状态对象,我们将利用React的React性质,而无需担心如何对浏览器进行更改。 React将为我们做到这一点。

But, our Button component is currently a function component. Function components cannot have state, so we need to upgrade this component to a class component first.

但是,我们的Button组件当前是一个功能组件。 功能组件不能具有状态,因此我们需要首先将该组件升级为类组件。

This is very simple. We first define a class that extends React.Component

这很简单。 我们首先定义一个扩展React.Component的类

class Button extends React.Component { }

In that class we define a render function, which returns the component’s JSX; the HTML button in our case.

在该类中,我们定义了一个render函数,该函数返回组件的JSX; 在我们的案例中是HTML按钮。

render() {  return (    <button>1</button>  );}

This is a little bit more code, but we can now use a private state on the Button component!

这是更多代码,但是我们现在可以在Button组件上使用私有状态!

To use a state object we first need to initialize it. The state object is a simple instance property, so we can initialize it inside the constructor function of the Button class. We just define the normal constructor function (which receives a props object in React) and call the super method to honor the inheritance of the component.

要使用状态对象,我们首先需要对其进行初始化。 状态对象是一个简单的实例属性,因此我们可以在Button类的构造函数中对其进行初始化。 我们只定义普通的构造函数(在React中接收一个props对象),然后调用super方法来继承组件的继承。

constructor(props) {  super(props);  this.state = { counter: 1 };}

After that, we initialize this.state to whatever we want. The keys of this state object are the various elements of the state. For our case, we need a counter state, which starts from 1.

之后,我们将this.state初始化为我们想要的任何东西。 此状态对象的键是状态的各种元素。 对于我们的情况,我们需要一个从1开始的counter状态。

Inside the render function, since we can write any JavaScript expression within curly brackets, we can read the value of the new counter state element that we initialized on the state using this.state.counter.

在render函数内部,因为我们可以在大括号内编写任何JavaScript表达式,所以我们可以使用this.state.counter读取在状态上初始化的新counter状态元素的值。

render() {  return (    <button>{this.state.counter}</button>  );}

The “this” keyword refers to the component instance we are handing off to ReactDOM.

this ”关键字是指我们要移交给ReactDOM的组件实例。

You can try and change that counter state to see how the button will render the values you put on the state.

您可以尝试更改该计数器状态,以查看按钮将如何呈现您放置在该状态上的值。

There is another shorter syntax to define the initial state, which is to simply use a class property without a constructor call:

还有另一种较短的语法来定义初始状态,即仅使用类属性而无需构造函数调用:

class Button extends React.Component {  state = { counter: 1 };    render() {    return (      <button>{this.state.counter}</button>    );  }}

This is not yet part of the official JavaScript language but it will be soon. The syntax works at the jsComplele REPL playground because that tool is using Babel to transpile it to the supported JavaScript that the browser will understand.

这还不是官方JavaScript语言的一部分,但很快就会发布。 该语法可在jsComplele REPL游乐场使用,因为该工具正在使用Babel将其转换为浏览器将理解的受支持JavaScript。

When you configure your own React application you’ll have to use something like Babel anyway to compile JSX into JavaScript. It is an easy win to also include and use the JavaScript features that are well on their way to becoming an official part of the language.

当配置自己的React应用程序时,无论如何都必须使用Babel之类的东西将JSX编译为JavaScript。 轻松地包含并使用成为该语言正式组成部分JavaScript功能也很容易。

In the Button example so far, we have a state object and an HTML button element that displays a counter value that we initialized on the state. Now we need to change that value when we click the button. We need to define a click handler on that button.

到目前为止,在Button示例中,我们有一个状态对象和一个HTML按钮元素,该元素显示一个在状态上初始化的计数器值。 现在,我们需要在单击按钮时更改该值。 我们需要在该按钮上定义一个单击处理程序。

React comes with normalized events that are easy to use. For this case, we need the onClick event, which we define on the HTML button element itself:

React带有易于使用的规范化事件。 对于这种情况,我们需要在HTML按钮元素本身上定义的onClick事件:

function F() {}
<button onClick={F} />

Unlike DOM event handlers, which use a string, React event handlers use an actual JavaScript function. This function can be a global one (like F above), or an inline function:

与使用字符串的DOM事件处理程序不同,React事件处理程序使用实际JavaScript函数。 此函数可以是全局函数(例如上面的F ),也可以是内联函数:

<button onClick={() => {}} />

However, the standard practice is to define a function on the class component itself. Let’s call it handleClick and we can define it on the component as an instance property:

但是,标准做法是在类组件本身上定义一个函数。 让我们将其称为handleClick ,我们可以在组件上将其定义为实例属性:

class Button extends React.Component {  state = { counter: 1 };    handleClick = () => {    console.log('Button is clicked!!');  };    render() {    return (      <button onClick={this.handleClick}>        {this.state.counter}      </button>    );  }}

We are using the modern class field syntax, which allows us to use arrow functions that are bound to the component instance. handleClick will now act as a prototype function on this class. Inside handleClick the keyword “this” refers to the component instance that we are mounting in the DOM.

我们正在使用现代的类字段语法,该语法使我们能够使用绑定到组件实例的箭头函数。 handleClick现在将充当此类的原型函数。 在handleClick内部,关键字“ this ”是指我们正在DOM中安装的组件实例。

handleClick ’s job is easy: read the current counter value from the state object using this.state.counter. Then increment this value and update the component state with the new incremented value.

handleClick的工作很简单:使用this.state.counter从状态对象读取当前计数器值。 然后增加该值,并使用新的增加的值更新组件状态。

We can use React’s built-in setState method, which is available on every class component instance, to update a component state.

我们可以使用React的内置setState方法来更新组件状态,该方法在每个类组件实例上都可用。

The button will now increment its label on every click.

现在,该按钮将在每次单击时增加其标签。

This was simple and powerful! We defined an event handler for the onClick method. Every time the user clicks the button the handleClick function will be executed. The function reads the current state of the counter value, increments it, and then sets the state to the new incremented value. React takes care of all the rendering needed after these changes so you do not have to worry about that.

这是简单而强大的! 我们为onClick方法定义了一个事件处理程序。 每次用户单击按钮时,都会执行handleClick函数。 该函数读取计数器值的当前状态,对其进行递增,然后将该状态设置为新的递增值。 在这些更改之后,React会处理所有需要的渲染,因此您不必为此担心。

Note that we did not update the state object directly. We have to use React’s setState method when we want to update any element on the state. You can’t for example do this:

请注意,我们没有直接更新状态对象。 当我们想要更新状态上的任何元素时,我们必须使用React的setState方法。 例如,您不能执行以下操作:

// WRONG:this.state.counter = this.state.counter + 1;

React’s setState method is an asynchronous one which schedules an update. Multiple setState calls might potentially be batched for performance. Since we are both reading and writing to the state object inside the handleClick function, we could hit a race condition. The general rule of thumb is whenever you need to update the state using a value from the current state, use the other contract of the setState method. This receives a function reference instead of an object as its first argument:

React的setState方法是一个异步方法,它调度更新。 可能会批处理多个setState调用以提高性能。 由于我们正在读写handleClick函数中的状态对象,因此我们可能遇到竞争状况。 一般的经验法则是,当您需要使用当前状态中的值更新状态时,请使用setState方法的另一个协定。 这将接收函数引用而不是对象作为其第一个参数:

this.setState((prevState) => {});

This function receives a prevState object that we can confidently use without worrying about race conditions. The function returns the object that we want React to use to set the state. Our counter value example above becomes:

此函数接收一个prevState对象,我们可以放心使用它,而不必担心竞争条件。 该函数返回我们希望React用于设置状态的对象。 我们上面的counter值示例变为:

this.setState((prevState) => ({  counter: prevState.counter + 1 }));

You only need to use this second syntax of setState if your update depends on the current state. However, it may be a good idea to make a habit of always using the second function-argument syntax.

如果更新取决于当前状态,则仅需要使用setState第二种语法。 但是,养成始终使用第二个函数参数语法的习惯可能是一个好主意。

Here is the final code:

这是最终代码:

class Button extends React.Component {  state = { counter: 1 };    handleClick = () => {    this.setState((prevState) => ({      counter: prevState.counter + 1     }));  };    render() {    return (      <button onClick={this.handleClick}>        {this.state.counter}      </button>    );  }}
ReactDOM.render(<Button />, mountNode);

Test it out and if you have any questions let me know in the comments below.

测试一下 ,如果您有任何问题,请在下面的评论中告诉我。

This article is a write-up of part of my Pluralsight course — React.js: Getting Started. I cover similar content in video format there.

本文是我的Pluralsight课程“ React.js:入门”的一部分的文章。 我在那里以视频格式介绍了类似的内容。

Learning React or Node? Checkout my books:

学习React还是Node? 结帐我的书:

  • Learn React.js by Building Games

    通过构建游戏学习React.js

  • Node.js Beyond the Basics

    超越基础的Node.js

翻译自: https://www.freecodecamp.org/news/how-to-write-your-first-react-js-component-d728d759cabc/

编写react组件

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/5/7840.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息