This article mainly talks about the use of react.js, so that everyone can see that react is not as difficult as imagined. Now let us take a look at the specific content of this article
1, React are all componentized
React is designed around the concept of reusable components. You define small components and combine them together to form larger components.
Regardless of size, all components are reusable, even across different projects.
React The simplest form of a component is an ordinary JavaScript function:
function Button (props) { // 这里返回一个 DOM元素,例如: return <buttontype="submit">{props.label}</button>; } // 将按钮组件呈现给浏览器 ReactDOM.render(<Buttonlabel="Save" />, mountNode)
Example 1: Edit the above code and press the Ctrl Enter key to execute (Translator's Note: The translation does not have this function for the time being, please visit the original text to use this function, the same below)
Buttons in brackets labels will be explained later. Don't worry about them now. ReactDOM will also be explained later, but if you want to test this example and all the following examples, the above render function is necessary. (What React will take over and control is the second parameter of ReactDOM.render, which is the target DOM element). In the jsComplete REPL, you can use the special variable mountNode.
Example 1 Notes:
The first letter of the component name is capitalized, Button. This is necessary because we will be dealing with a mix of HTML elements and React elements. Lowercase names are reserved for HTML elements. In fact, name your React component "button" and you'll find that ReactDOM ignores this function and just renders it as a regular empty HTML button.
Each component receives a list of properties, just like an HTML element. In React, this list is called a property. Although you can name a function whatever you want.
In the return output of the Button function component above, we strangely wrote a piece of code that looks like HTML. This isn’t actually JavaScript or HTML, and honestly, it’s not even React.js. Yet it's so popular that it's become the default in React applications. This is called JSX, which is a JavaScript extension. JSX is also a compromise! Go ahead and try and return other HTML elements in the above function to see how they are supported (for example, returning a text input element).
2、What does JSX output?
The above Example 1 can be written in pure React.js without JSX, as follows:
function Button (props) { return React.createElement( "button", { type: "submit" }, props.label ); } // 要使用 Button,你可以这么做 ReactDOM.render( React.createElement(Button, { label:"Save" }), mountNode );
Example 2: Writing React components without using JSX
In the React top-level API, the createElement function is the main function. This is 1 of 7 APIs you need to learn. React’s API is just so small.
Just like the DOM itself has a document.createElement function to create an element specified by the tag name, React's createElement function is a high-level function that has the same functionality as document.createElement , but it can also be used to create an element that represents a React component. We are using the latter when we use the Button component in Example 2 above.
Unlike document.createElement, React's createElement receives a dynamic parameter after receiving the second parameter, which represents the child element of the created element. So createElement actually creates a tree.
Here is an example of this:
const InputForm = React.createElement( "form", { target: "_blank", action:"https://google.com/search" }, React.createElement("p",null, "Enter input and click Search"), React.createElement("input", {className: "big-input" }), React.createElement(Button, { label:"Search" }) ); // InputForm 使用 Button组件,所以我们需要这样做: function Button (props) { return React.createElement( "button", { type: "submit" }, props.label ); } // 然后我们可以通过 .render方法直接使用 InputForm ReactDOM.render(InputForm, mountNode);
例 3:React创建元素的 API
上面例子中的一些事情值得注意:
InputForm 不是一个 React组件;它仅仅是一个 React 元素。这就是为什么我们可以在ReactDOM.render 中直接使用它并且可以在调用时不使用
React.createElement函数在前两个参数后接收了多个参数。从第3个参数开始的参数列表构成了创建元素的子项列表。
我们可以嵌套 React.createElement调用,因为它是 JavaScript。
当这个元素不需要属性时,React.createElement的第二个参数可以为空或者是一个空对象。
我们可以在 React 组件中混合HTML 元素。你可以将 HTML 元素作为内置的 React组件。
React 的 API试图和 DOM API 一样,这就是为什么我们在 input 元素中使用 className 代替 class 的原因。我们都希望如果 React 的 API 成为 DOM API 本身的一部分,因为,你知道,它要好得多。
上述的代码是当你引入 React 库的时候浏览器是怎样理解的。浏览器不会处理任何 JSX 业务。然而,我们更喜欢看到和使用 HTML,而不是那些 createElement 调用(想象一下只使用document.createElement 构建一个网站!)。这就是 JSX 存在的原因。取代上述调用 React.createElement 的方式,我们可以使用一个非常简单类似于HTML 的语法:
const InputForm = <form target="_blank"action="https://google.com/search"> <p>Enter input and clickSearch</p> <inputclassName="big-input" name="q" /> <Buttonlabel="Search" /> </form>; // InputForm “仍然”使用 Button 组件,所以我们也需要这样。 // JXS 或者普通的表单都会这样做 function Button (props) { // 这里返回一个 DOM元素。例如: return <buttontype="submit">{props.label}</button>; } // 然后我们可以直接通过 .render使用 InputForm ReactDOM.render(InputForm, mountNode);
例 4:为什么在 React中 JSX 受欢迎(和例3 相比)
注意上面的几件事:
这不是 HTML 代码。比如,我们仍然可以使用 className 代替 class。
我们仍在考虑怎样让上述的 JavaScript看起来像是 HTML。看一下我在最后是怎样添加的。
我们在上面(例 4)中写的就是 JSX。然而,我们要将编译后的版本(例 3)给浏览器。要做到这一点,我们需要使用一个预处理器将 JSX 版本转换为 React.createElement 版本。
这就是 JSX。这是一种折中的方案,允许我们用类似 HTML 的语法来编写我们的 React 组件,这是一个很好的方法。
“Flux” 在头部作为韵脚来使用,但它也是一个非常受欢迎的应用架构,由 Facebook推广。最出名的是 Redux,Flux 和 React 非常合适。
JSX,可以单独使用,不仅仅适用于 React。
3、 你可以在 JavaScript的任何地方使用 JSX
在 JSX 中,你可以在一对花括号内使用任何 JavaScript 表达式。
const RandomValue = () => <p> { Math.floor(Math.random() * 100)} </p>; // 使用: ReactDOM.render(<RandomValue />,mountNode);
例 5:在 JSX中使用 JavaScript 表达式
任何 JavaScript 表达式可以直接放在花括号中。这相当于在 JavaScript 中插入 ${} 模板。
这是 JSX 内唯一的约束:只有表达式。例如,你不能使用 if 语句,但三元表达式是可以的。
JavaScript 变量也是表达式,所以当组件接受属性列表时(不包括 RandomValue组件,props 是可选择的),你可以在花括号里使用这些属性。我们在上述(例 1)的 Button 组件是这样使用的。
JavaScript 对象也是表达式。有些时候我们在花括号中使用 JavaScript对象,这看起来像是使用了两个花括号,但是在花括号中确实只有一个对象。其中一个用例就是将 CSS 样式对象传递给响应中的特殊样式属性:
const ErrorDisplay = ({message}) => <p style={ { color: 'red',backgroundColor: 'yellow' } }> {message} </p>; // 使用 ReactDOM.render( <ErrorDisplay message="These aren't thedroids you're looking for" />, mountNode );
例 6:一个对象传递特殊的 React样式参数
注意我解构的只是在属性参数之外的信息。这只是 JavaScript。还要注意上面的样式属性是一个特殊的属性(同样,它不是 HTML,它更接近 DOM API)。我们使用一个对象作为样式属性的值并且这个对象定义样式就像我们使用 JavaScript 那样(我们可以这样做)。
你可以在 JSX 中使用 React 元素。因为这也是一个表达式(记住,一个 React 元素只是一个函数调用):
const MaybeError = ({errorMessage}) => <p> {errorMessage &&<ErrorDisplay message={errorMessage} />} </p>; // MaybeError 组件使用 ErrorDisplay组件 const ErrorDisplay = ({message}) => <p style={ { color: 'red',backgroundColor: 'yellow' } }> {message} </p>; // 现在我们使用 MaybeError组件: ReactDOM.render( <MaybeError errorMessage={Math.random() >0.5 ? 'Not good' : ''} />, mountNode );
例 7:一个 React元素是一个可以通过 {} 使用的表达式
上述 MaybeError 组件只会在有errorMessage 传入或者另外有一个空的 p 才会显示 ErrorDisplay 组件。React 认为 {true}、 {false}
{undefined} 和 {null} 是有效元素,不呈现任何内容。
我们也可以在 JSX 中使用所有的JavaScript 的集合方法(map、reduce 、filter、 concat 等)。因为他们返回的也是表达式:
const Doubler = ({value=[1, 2, 3]}) => <p> {value.map(e => e * 2)} </p>; // 使用下面内容 ReactDOM.render(<Doubler />, mountNode);
例 8:在 {}中使用数组
请注意我是如何给出上述 value 属性的默认值的,因为这全部都只是 JavaScript。注意我只是在 p 中输出一个数组表达式。React 是完全可以的。它只会在文本节点中放置每一个加倍的值。
4、 你可以使用 JavaScript类写 React 组件
简单的函数组件非常适合简单的需求,但是有的时候我们需要的更多。React也支持通过使用 JavaScript 类来创建组件。这里 Button 组件(在例 1 中)就是使用类的语法编写的。
class Button extends React.Component { render() { return<button>{this.props.label}</button>; } } // 使用(相同的语法) ReactDOM.render(<Buttonlabel="Save" />, mountNode);
例 9:使用 JavaScript类创建组件
类的语法是非常简单的:定义一个扩展的 React.Component类(另一个你需要学习的 React 的顶级 API)。该类定义了一个单一的实例函数 —— render(),并使函数返回虚拟 DOM 对象。每一次我们使用基于类的 Button 组件(例如,通过 ),React 将从这个基于类的组件中实例化对象,并在 DOM 树中使用该对象。
这就是为什么上面的例子中我们可以在 JSX中使用 this.props.label 渲染输出的原因,因为每一个组件都有一个特殊的称为props 的 实例 属性,这让所有的值传递给该组件时被实例化。
由于我们有一个与组件的单个使用相关联的实例,所以我们可以按照自己的意愿定制该实例。例如,我们可以通过使用常规 JavaScript构造函数来构造它:
class Button extends React.Component { constructor(props) { super(props); this.id = Date.now(); } render() { return <buttonid={this.id}>{this.props.label}</button>; } } // 使用 ReactDOM.render(<Buttonlabel="Save" />, mountNode);
例 10:自定义组件实例
我们也可以定义类的原型并且在任何我们希望的地方使用,包括在返回的 JSX输出的内部:
class Button extends React.Component { clickCounter = 0; handleClick = () => { console.log(`Clicked: ${++this.clickCounter}`); } render() { return ( <button id={this.id}onClick={this.handleClick}> {this.props.label} </button> ); } } // 使用 ReactDOM.render(<Buttonlabel="Save" />, mountNode);
例 11:使用类的属性(通过单击保存按钮进行测试)
注意上述例 11 中的几件事情
handleClick 函数使用 JavaScript 新提出的 class-field syntax 语法。这仍然是 stage-2,但是这是访问组件安装实例(感谢箭头函数)最好的选择(因为很多原因)。然而,你需要使用类似 Babel 的编译器解码为 stage-2(或者仅仅是类字段语法)来让上述代码工作。 jsComplete REPL 有预编译功能。
// 错误:
onClick={this.handleClick()}
// 正确:
onClick={this.handleClick}
5、React中的事件:两个重要的区别
当处理 React 元素中的事件时,我们与 DOM API 的处理方式有两个非常重要的区别:
所有 React 元素属性(包括事件)都使用 camelCase 命名,而不是 lowercase。例如是 onClick 而不是 onclick。
我们将实际的 JavaScript 函数引用传递给事件处理程序,而不是字符串。例如是 onClick={handleClick} 而不是onClick="handleClick"。
React 用自己的对象包装 DOM对象事件以优化事件处理的性能,但是在事件处理程序内部,我们仍然可以访问 DOM对象上所有可以访问的方法。React 将经过包装的事件对象传递给每个调用函数。例如,为了防止表单提交默认提交操作,你可以这样做:
class Form extends React.Component { handleSubmit = (event) => { event.preventDefault(); console.log('Form submitted'); }; render() { return ( <formonSubmit={this.handleSubmit}> <buttontype="submit">Submit</button> </form> ); } } // 使用 ReactDOM.render(<Form />, mountNode);
例 12:使用包装过的对象
6、每一个 React组件都有一个故事:第 1 部分
以下仅适用于类组件(扩展 React.Component)。函数组件有一个稍微不同的故事。
首先,我们定义了一个模板来创建组件中的元素。
然后,我们在某处使用 React。例如,在 render 内部调用其他的组件,或者直接使用 ReactDOM.render。
然后,React 实例化一个对象然后给它设置 props 然后我们可以通过 this.props 访问。这些属性都是我们在第 2 步传入的。
因为这些全部都是 JavaScript,constructor方法将会被调用(如果定义的话)。这是我们称之为的第一个:组件生命周期方法。
接下来 React 计算渲染之后的输出方法(虚拟 DOM 节点)。
因为这是 React 第一次渲染元素,React将会与浏览器连通(代表我们使用 DOM API)来显示元素。这整个过程称为 mounting。
接下来 React 调用另一个生命周期函数,称为 componentDidMount。我们可以这样使用这个方法,例如:在 DOM 上做一些我们现在知道的在浏览器中存在的东西。在此生命周期方法之前,我们使用的 DOM 都是虚拟的。
一些组件的故事到此结束,其他组件得到卸载浏览器 DOM中的各种原因。在后一种情况发生时,会调用另一个生命周期的方法,componentWillUnmount。
任何 mounted 的元素的状态都可能会改变。该元素的父级可能会重新渲染。无论哪种情况,mounted 的元素都可能接收到不同的属性集。React 的魔力就是这儿,我们实际上需要的正是 React 的这一点!在这一点之前,说实话,我们并不需要 React。
组价的故事还在继续,但是在此之前,我们需要理解我所说的这种状态。
7、React组件可以具有私有状态
以下只适用于类组件。我有没有提到有人叫表象而已的部件 dumb?
状态类是任何 React 类组件中的一个特殊字段。React 检测每一个组件状态的变化,但是为了 React 更加有效,我们必须通过 React 的另一个 API 改变状态字段,这就是我们要学习的另一个 API —— this.setState:
class CounterButton extends React.Component { state = { clickCounter: 0, currentTimestamp: new Date(), }; handleClick = () => { this.setState((prevState) => { return { clickCounter:prevState.clickCounter + 1 }; }); }; componentDidMount() { setInterval(() => { this.setState({currentTimestamp: new Date() }) }, 1000); } render() { return ( <p> <buttononClick={this.handleClick}>Click</button> <p>Clicked:{this.state.clickCounter}</p> <p>Time:{this.state.currentTimestamp.toLocaleString()}</p> </p> ); } } // 使用 ReactDOM.render(<CounterButton />,mountNode);
例 13:setState的 API
这可能是最重要的一个例子因为这将是你完全理解 React基础知识的方式。这个例子之后,还有一些小事情需要学习,但从那时起主要是你和你的 JavaScript 技能。
让我们来看一下例 13,从类开始,总共有两个,一个是一个初始化的有初始值为 0 的 clickCounter 对象和一个从 new Date() 开始的 currentTimestamp。
另一个类是 handleClick 函数,在渲染方法中我们给按钮元素传入 onClick 事件。通过使用 setState 的 handleClick 方法修改了组件的实例状态。要注意到这一点。
另一个我们修改状态的地方是在一个内部的定时器,开始在内部的componentDidMount生命周期方法。它每秒钟调用一次并且执行另一个函数调用this.setState。
在渲染方法中,我们使用具有正常读语法的状态上的两个属性(没有专门的 API)。
现在,注意我们更新状态使用两种不同的方式:
通过传入一个函数然后返回一个对象。我们在 handleClick函数内部这样做。
通过传入一个正则对象,我们在在区间回调中这样做。
这两种方式都是可以接受的,但是当你同时读写状态时,第一种方法是首选的(我们这样做)。在区间回调中,我们只向状态写入而不读它。当有问题时,总是使用第一个函数作为参数语法。伴随着竞争条件这更安全,因为 setstate实际上是一个异步方法。
How should we update the status? We return an object with the value we want to update. Note that when calling setState, we pass in all or none of the properties from the state. This is totally fine because setState actually merges the function argument you passed it (the return value) with the existing state, so not specifying a property when calling setState means we don't want to change the property (but not delete it) .
8, React will react
The name of React is from the state Derived from the reaction of change (although there is no reaction, it is also in a timetable). There's a joke here, React should be named Schedule!
However, when the state of any component is updated, what we observe with the naked eye is a reaction to that update, and automatically reflects the update in the browser DOM (if necessary ).
Consider the input to the rendering function as two types:
Attributes passed in through the parent element
And internal private state that can be updated at any time
When the input to the render function changes, the output may also change.
React saves a history of renders, and when it sees a render that is different from the previous one, it calculates the difference between them and adds it Effectively translated into actual DOM operations performed in the DOM.
9, React is your code
You can think of React as The proxy we use to communicate with the browser. Take the current timestamp display above as an example. Instead of having to manually go to the browser and call DOM API operations every second to find and update the p#timestamp element, we just change the state attribute of the component, and React does the work on our behalf to communicate with the browser. I believe this is the real reason why React is so popular; we just don't like talking to Mr. Browser (and the many dialects of the DOM language it speaks), and React is passed to us voluntarily, for free!
10, Every React component has a story: Part 2
Now we know When the state of a component changes, let's take a look at the last few concepts about this process.
A component may need to be re-rendered when its state is updated, or when its parent process decides to change the properties it passed to the component.
If the latter occurs, React will call another life cycle method: componentWillReceiveProps.
If the state object or passed properties change, React has an important decision to make: should the component update in the DOM? That's why it calls another important lifecycle method shouldComponentUpdate. This method is a practical matter, so if you need to customize or optimize the rendering process yourself, you must answer this question by returning true or false.
If there is no custom shouldComponentUpdate, React's default event can be handled well in most cases.
First of all, another life cycle method will be called at this time: componentWillUpdate. React will then calculate the newly rendered output and compare it to the last rendered output.
If the rendered output is the same as before, React does not process it (no need to talk to Mr. Browser).
If there is a difference, React communicates the difference to the browser, like we saw before.
In any case, once an updater occurs, no matter how (even with the same output), React will call the final life cycle method: componentDidUpdate.
Lifecycle methods are escape hatches. If you don't do anything special, you can create a complete application without them. They are very convenient for analyzing what is happening in the application and further optimizing the performance of React updates
This article ends here (if you want to see more, go to the PHP Chinese website Learn in the column of the React User Manual). If you have any questions, you can leave a message below.
The above is the detailed content of How to use React.js? Introduction to the simple use of react.js (with examples). For more information, please follow other related articles on the PHP Chinese website!