React js教程:React 中的片段和纯组件(12)
本文是React 教程系列的一部分。您可以在此处找到本系列之前所有帖子的链接
介绍
在上一篇文章中,我们了解了 React 生命周期的组件以及它是如何在 React 中使用的。在本文中,我们将了解 Fragment 和 Pure Component 及其在 React 中的重要性。
Fragments
在 React 中,当在 render() 方法中返回任何元素时,必须将多个元素包装在主容器中。为了减轻添加容器以添加多个元素的麻烦,引入了 Fragment 的概念。在 <React.Fragment> 内部,不需要添加任何父容器。
Fragment 的概念是在 React v16 之后引入的,所以要使用 Fragment 的概念,你的应用程序必须更新到 React 16.2 版本让我们看一个有多个元素的代码。
例如,下面的代码有多个元素。
import React,{Component} from '.react';
class Fragments extends Component{
render(){
return(
<p>Test</p>
<p>Test 1</p>
<p>Test 2</p>
)
}
}
下面,它将显示错误,因为 JSX 必须有 1 个父元素。
import React,{Component} from '.react';
class Fragments extends Component{
render(){
return(
<p>Test</p>,
<p>Test 1</p>,
<p>Test 2</p>
)
}
}
输出将显示如下。
import React,{Component} from 'react';
class Fragments extends Component{
render(){
return[
<p>Test</p>,
<p>Test 1</p>,
<p>Test 2</p>
]
}
}
export default Fragments;
现在,输出将显示如下。
import React,{Component,Fragment} from 'react';
class Fragments extends Component{
render(){
return(
<Fragment>
<p>Test</p>
<p>Test 1</p>
<p>Test 2</p>
</Fragment>
)
}
}
export default Fragments;
输出将显示如下。
import React,{Component} from 'react';
class Fragments extends Component{
render(){
return(
<>
<p>Test</p>
<p>Test 1</p>
<p>Test 2</p>
</>
)
}
}
export default Fragments;
输出将显示与上面相同。
虽然使用 React.Fragment 不会向 DOM 添加任何 HTMLElement,但 React.Fragment 节点是作为父标记添加到 JSX 元素的,而不会向 DOM 添加任何额外元素。
片段(Fragments)的好处
- 一些css机制,比如CSS Grid、Flexbox,有一些特殊的父子关系,在中间添加div使得在提取逻辑组件的同时很难保持想要的布局。
- 这提供了更快且使用更少的内存,因为它不会创建任何额外的节点。当应用程序非常大并且使用这些片段可以防止创建不必要的元素时,这会带来好处。
- 改进了 JSX 的语义标记。如果需要,可以使用包装器的元素,而不是因为它们是强制的。
- 它提供了更高的渲染性能和更少的内存开销。
片段(Fragments)的使用
返回元素组
在这里,片段可用于返回元素列表,而无需将它们包装在容器或数组中。这在返回表单和文本标记时很有用,因为将它们包装在 div 中可能会导致应用样式时出现问题。
根据下面的代码,我们定义了输入文本和按钮。
import React,{Component,Fragment} from 'react';
class Fragments extends Component{
constructor(props){
super(props);
this.state={
UserName : ''
}
}
render(){
return(
<Fragment>
<label>Name : </label>
<input type='text' name='txtuser' id='textuser' value={this.UserName}/>
<button> Click Me !</button>
</Fragment>
)
}
}
export default Fragments;
输出显示如下。
有条件地渲染元素组
片段允许有条件地呈现元素,而无需添加额外的标记标签。我们可以在 Fragment 中使用三元或 case 语句在浏览器中显示输出。让我们看看下面的例子。
import React,{Component,Fragment} from 'react';
const info = {
color: 'blue',
fontWeight: 'bold',
padding: '4px'
}
const error = {
color: 'red',
fontWeight: 'bold',
padding: '4px'
}
class Fragments extends Component{
constructor(props){
super(props);
this.state={
UserName : "",
isClicked : false
}
this.handleSubmit = this.handleSubmit.bind(this);
this.handleInput = this.handleInput.bind(this);
}
handleSubmit(){
this.setState({
isClicked :true
});
}
handleInput(e){
this.setState({
UserName: e.target.value
})
}
render(){
return(
<Fragment>
<label>Name : </label>
<input type='text' name='txtuser' id='textuser' value={this.state.UserName} onChange={this.handleInput}/>
<button onClick={this.handleSubmit}> Click Me !</button><br/>
{this.state.isClicked ? (
<p style={info}>You clicked button, your name is <b>{this.state.UserName}</b></p>
):(
<p style={error}>Please Click button</p>
)}
</Fragment>
)
}
}
export default Fragments;
输出将显示如下。
带数组的片段
React 提供了 Fragments 概念来代替数组。
使用 Fragment 有以下好处,
- 使用数组时,子元素必须用逗号分隔 – 片段不存在相同的情况。
- 一个数组需要一个key来防止React key;片段不存在相同的情况。
- 在 Array 中,字符串必须用双引号引起来,而在片段中它不包含这样的引号
例如,要定义数组,我们有以下代码。
return[
"This is my React Application.",
<h2 key="heading-1">Include Introduction</h2>,
"Now moving towards.",
<h2 key="heading-2">The Complex chapters </h2>,
"And provide practical session."
];
render(){
return(
<Fragment>
This is my React Application
<h2>Include Introduction</h2>
Now moving towards
<h2>The Complex chapters </h2>
And provide practical session
</Fragment>
);
}
纯组件
在 React 中,只有当组件为相同的 state 和 props 呈现相同的输出并且其返回值对于相同的输入值始终相同时,才被声明为纯组件。Component extends React.PureComponent 基类被视为纯组件。
Pure Component 包括一些性能改进和渲染优化,因为 React 实现了 shouldComponentUpdate() 方法来对 props 和 state 进行浅层比较。
纯组件的 shouldComponentUpdate() 方法只是浅层比较对象。在使用复杂数据结构的情况下,它可以为更深层次的差异生成假阴性。当您拥有简单的道具和状态或使用 forceUpdate() 时,您可以使用这种方法,或者您可以使用不可变对象,以防进行深入的数据比较。
当 PureComponent 使用 shouldComponentUpdate() 方法时,它会跳过整个组件子树的 props 更新。因此,在使用它时,请确保所有孩子都是纯洁的。
例如,在 React.Component 的情况下
import React from 'react';
class Calculation extends React.Component{
constructor(props){
super(props);
this.state={
firstName : "",
fullName:""
}
this.handleFirstName = this.handleFirstName.bind(this);
this.handleClick = this.handleClick.bind(this);
}
handleFirstName(e){
this.setState({
firstName : e.target.value
});
}
handleClick(e){
this.setState({
fullName : this.state.firstName
});
}
render(){
console.log('rendered' + this.state.fullName);
return(
<div>
<input type="text" value={this.state.firstName} placeholder="First Name" onChange={this.handleFirstName}></input>
<button onClick={this.handleClick}>Click Me!</button>
<p> {this.state.fullName}</p>
</div>
)
}
}
export default Calculation;
输出将显示如下。
每次单击按钮时,控制台中的上述输出都会调用 render 方法,即使文本框中没有进行任何更改。
现在,将 React.Component 更新为 React.PureComponent
import React from 'react';
class Calculation extends React.PureComponent{
constructor(props){
super(props);
this.state={
firstName : "",
fullName:""
}
this.handleFirstName = this.handleFirstName.bind(this);
this.handleClick = this.handleClick.bind(this);
}
handleFirstName(e){
this.setState({
firstName : e.target.value
});
}
handleClick(e){
this.setState({
fullName : this.state.firstName
});
}
render(){
console.log('rendered' + this.state.fullName);
return(
<div>
<input type="text" value={this.state.firstName} placeholder="First Name" onChange={this.handleFirstName}></input>
<button onClick={this.handleClick}>Click Me!</button>
<p> {this.state.fullName}</p>
</div>
)
}
}
export default Calculation;
现在,观察下面的输出。
现在查看控制台,如果文本框中没有更改,则不会每次都调用按钮渲染方法。
浅比较
在使用纯组件时,术语浅比较很重要。浅比较是指 2 种原始类型,原始类型和复杂类型,
原始类型
例如,在原始类型中,我们有 2 个值,a 和 b 任何类型,如字符串、布尔值或数字。如果两者属于相同类型且具有相同值,则浅比较 b 返回 true
例子,
let a = “Test”;
let b = “Test”;
console.log(a===b); // return true;
复杂类型
在像数组和对象这样的复杂类型中,如果两者具有相同的对象,则浅比较 b 返回 true
例子,
let a = {1,2,3}
let b = {1,2,3}
let c = a
console.log(a===b); // return false; point to different object
console.log(a===c); // return true, as it points to the same object
使用纯组件时要记住的要点:
- 如果父类扩展 PureComponent,那么我们必须确保子类也是纯的,以避免意外行为。
- 永远记住永远不要改变状态,状态总是返回一个反映新状态的新对象。
- 如果 props 和 state 没有变化,Pure Component 将不会被重新渲染。
- 纯组件应该用于小型应用程序。
概括
在本文中,我们了解了 Fragment 和 Pure Component 及其在 React 中的使用。此外,我们回顾了浅比较的概念。在下一篇文章中,我们将了解 memo 是一个功能组件,以及它与纯组件的区别。以及 React 中 Refs 的概念。
本系列的下一个 >>React 中的门户和错误边界
常见问题FAQ
- 程序仅供学习研究,请勿用于非法用途,不得违反国家法律,否则后果自负,一切法律责任与本站无关。
- 请仔细阅读以上条款再购买,拍下即代表同意条款并遵守约定,谢谢大家支持理解!