Maison > Article > interface Web > Pourquoi React recommande des composants fonctionnels
Raison : 1. La syntaxe des composants de fonction est plus courte et plus simple, ce qui facilite le développement, la compréhension et les tests ; 2. Une utilisation excessive de celle-ci dans les composants de classe rend la logique entière confuse ; 3. La fonction Hooks ne prend en charge que les composants de fonction ; 4. L'équipe React a effectué davantage d'optimisations pour les composants de fonction afin d'éviter les vérifications inutiles et les fuites de mémoire ; 5. Les composants fonctionnels ont une faible consommation de performances car les composants fonctionnels n'ont pas besoin de créer d'instances et sont exécutés lors du rendu, après avoir obtenu l'élément de réaction renvoyé. , détruisez directement tous les montants intermédiaires.
L'environnement d'exploitation de ce tutoriel : système Windows 7, version React18, ordinateur Dell G3.
Lors du développement à l'aide du framework React, il existe deux manières de créer des composants : en utilisant des fonctions et en utilisant des classes. Actuellement, les composants de fonction sont de plus en plus populaires. Ce qui suit utilise des exemples pour analyser les différences entre les composants fonctionnels et les composants de classe, et résume les raisons (avantages) de l'utilisation des composants fonctionnels.
Les composants de fonction et les composants de classe traitent JSX différemment, tout comme leurs noms, un composant de fonction est une fonction Javascript pure qui renvoie directement JSX ; React.Component et implémentez la méthode render, qui renvoie JSX. Voici un exemple :React.Component
,并实现render方法,render方法中返回JSX。下面举例说明:
import React from "react";
const FunctionalComponent = () => {
return <h1>Hello, world</h1>;
};
上面通过ES6箭头函数的形式定义了一个函数组件,函数体内直接返回JSX。如果你对箭头函数不熟悉,也可以写成下面这种形式:
import React from "react";
function FunctionalComponent() {
return <h1>Hello, world</h1>;
}
两种写法是一样的。
然后,来看看如何定义类组件,首先我们需要扩展React.Component
,然后在render方法中返回JSX,具体看下面的代码片段:
import React, { Component } from "react";
class ClassComponent extends Component {
render() {
return <h1>Hello, world</h1>;
}}
上面使用了ES6的解构赋值语法来导入模块,如果你对解构赋值语法不熟悉,也可以写成下面这种形式,会看上去更简洁一些:
import React from "react";
class ClassComponent extends React.Component {
render() {
return <h1>Hello, world</h1>;
}
}
当需要向一个组件传递数据的时候,我们使用props,比如<FunctionalComponent name="Shiori" />
,name就是Component的一个props属性,这里可以有更多属性。FunctionalComponent组件的函数形式的定义如下:
const FunctionalComponent = ({ name }) => {
return <h1>Hello, {name}</h1>;
};
或者不使用解构赋值
const FunctionalComponent = (props) => {
return <h1>Hello, {props.name}</h1>;
};
这种方式,你需要使用props.name
来获取name属性。
然后,我们来看看类组件如何使用props,
class ClassComponent extends React.Component {
render() {
const { name } = this.props;
return <h1>Hello, { name }</h1>;
}}
在类组件中,你需要使用this
来获取props,然后可以使用解构赋值获取name
属性。
在React项目中,我们不可避免的要处理状态变量。类组件直到最近才支持处理状态,然而,从React从16.8版本开始,函数组件支持钩子方法useState
,这样我们可以很方便的在函数组件中使用状态变量。下面通过一个counter计数器实例来说明它们的不同。
const FunctionalComponent = () => {
const [count, setCount] = React.useState(0);
return (
<div>
<p>count: {count}</p>
<button onClick={() => setCount(count + 1)}>Click</button>
</div>
);};
这里使用useState
钩子,它接收一个初始的state作为参数。在本例中,计数器从0开始,所以我们给count一个初始值0。
state的初始值支持各种数据类型,包括null,string或者object对象,只要是javascript允许的都可以。在=
号的左边,我们使用解构赋值的形式来接受useState的返回值,包括当前的状态变量和更新该变量的setter函数,即count
和setCount
class ClassComponent extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } render() { return ( <div> <p>count: {this.state.count} times</p> <button onClick={() => this.setState({ count: this.state.count + 1 })}> Click </button> </div> ); }}
Ce qui précède définit un composant de fonction sous la forme d'une fonction fléchée ES6, et le corps de la fonction renvoie directement JSX. Si vous n'êtes pas familier avec les fonctions fléchées, vous pouvez également les écrire sous la forme suivante :
onClick={() => this.setState((state) => { return { count: state.count + 1 }; })}
Les deux méthodes d'écriture sont les mêmes.
Ensuite, voyons comment définir un composant de classe. Nous devons d'abord étendre React.Component
, puis renvoyer JSX dans la méthode de rendu. Voir l'extrait de code suivant pour plus de détails :
const FunctionalComponent = () => { React.useEffect(() => { console.log("Hello"); }, []); return <h1>Hello, World</h1>;};🎜
Ce qui précède utilise la syntaxe d'affectation de déstructuration d'ES6 pour importer le module. Si vous n'êtes pas familier avec la syntaxe d'affectation de déstructuration, vous pouvez également. écrivez-le sous la forme suivante, qui aura l'air plus concise. :🎜🎜
class ClassComponent extends React.Component { componentDidMount() { console.log("Hello"); } render() { return <h1>Hello, World</h1>; }}🎜🎜🎜Passing props🎜🎜🎜
Lorsque nous devons transmettre des données à un composant, nous utilisons des accessoires, tels que comme <FunctionalComponent name="Shiori" /> ;
, le nom est un attribut props du composant, il peut y avoir plus d'attributs ici. La forme fonctionnelle du composant FunctionalComponent est définie comme suit :
🎜🎜
const FunctionalComponent = () => { React.useEffect(() => { return () => { console.log("Bye"); }; }, []); return <h1>Bye, World</h1>;};🎜<p data-pid="e-i4xpLf">Ou ne pas utiliser d'affectation de déstructuration🎜🎜</p> <pre class="brush:php;toolbar:false">class ClassComponent extends React.Component { componentWillUnmount() { console.log("Bye"); } render() { return <h1>Bye, World</h1>; }}🎜
Cette méthode aimable, vous devez utiliser props.name
pour obtenir l'attribut name. 🎜
Ensuite, voyons comment les composants de classe utilisent les accessoires, 🎜🎜rrreee🎜
Dans les composants de classe, vous devez utiliser this pour obtenir des accessoires, puis vous pouvez utiliser l'affectation de déstructuration pour obtenir l'attribut <code>name
. 🎜🎜🎜Gestion de l'état🎜🎜🎜
Dans les projets React, nous devons inévitablement gérer des variables d'état. Les composants de classe ne prenaient pas en charge la gestion de l'état jusqu'à récemment. Cependant, à partir de la version 16.8 de React, les composants de fonction prennent en charge la méthode hook useState
, afin que nous puissions facilement utiliser des variables d'état dans les composants de fonction. Ce qui suit utilise un contre-exemple pour illustrer leurs différences.
🎜🎜🎜Gestion des variables d'état dans les composants de fonction🎜🎜🎜rrreee🎜
Le hook useState
est utilisé ici, qui reçoit un état initial en paramètre . Dans cet exemple, le compteur démarre à 0, nous donnons donc à count une valeur initiale de 0. 🎜
La valeur initiale de state prend en charge divers types de données, y compris les objets null, chaîne ou objet, tant qu'elle est autorisée par javascript. Sur le côté gauche du numéro =
, nous utilisons la forme d'affectation de déstructuration pour accepter la valeur de retour de useState, y compris la variable d'état actuel et la fonction setter qui met à jour la variable, à savoir count
et setCount
. 🎜🎜🎜Gestion des variables d'état dans les composants de classe🎜🎜🎜rrreee🎜
与函数组件大同小异,首先我们要理解React.Component
的构造函数constructor
,react的官方文档对constructor的定义如下:
“The constructor for a React component is called before it is mounted. When implementing the constructor for a React.Component subclass, you should call super(props) before any other statement. Otherwise, this.props will be undefined in the constructor, which can lead to bugs.”
翻译一下,
React组件的constructor方法会在组件完全加载完成之前调用。在constructor方法中,你需要在第一行调用super(props),否则会报this.props是undefined的错误。
如果在类组件中,你没有实现constructor方法并调用super(props),那么所有的状态变量都将是undefined。所以,别忘记先定义constructor方法,在constructor方法中,我们需要给this.state一个初始值,像上面的代码那样。然后我们可以在JSX中使用this.state.count
来获取count的值,setter的使用也是类似的。
这里先定义一个onClick
方法,后面会用到,
onClick={() =>
this.setState((state) => {
return { count: state.count + 1 };
})}
这里注意setState()方法接收的是个箭头函数,而箭头函数的参数是state和props,props是可选的,这里没用到就没写。
React的组件在它整个的渲染的过程中,有它的生命周期。如果你之前一直使用类组件,刚刚接触函数组件,你可能会疑惑,为什么在函数组件中没有componentDidMount()
这类的生命周期方法?但是别急,有其他的钩子函数可以使用。
类组件的生命周期函数componentDidMount
会在首次渲染完成之后调用。首次渲染完成之前会调用componentWillMount
,但是这个方法在新版本的React中不推荐使用了。
在函数组件中,我们使用useEffect
钩子函数来处理生命周期内的事件,像下面这样,
const FunctionalComponent = () => {
React.useEffect(() => {
console.log("Hello");
}, []);
return <h1>Hello, World</h1>;};
useEffect
有两个参数,第一个是箭头函数,第二个是[]
,[]
里面是变化的state(s)
。什么意思呢?就是[]
中的状态变化了,箭头函数会被调用。如果像现在这样写个[]
,那箭头函数只会在组件第一次渲染之后调用一次,其功能类似下面类组件的componentDidMount
。
class ClassComponent extends React.Component {
componentDidMount() {
console.log("Hello");
}
render() {
return <h1>Hello, World</h1>;
}}
const FunctionalComponent = () => {
React.useEffect(() => {
return () => {
console.log("Bye");
};
}, []);
return <h1>Bye, World</h1>;};
这里注意return的也是一个箭头函数,这个函数就是在卸载阶段执行的。当你需要执行一些卸载操作,可以放在这里,比如你可以把clearInterval放在这里,避免内存泄漏。使用useEffect钩子函数的最大好处就是可以把加载函数和卸载函数放在一个同一个地方。这里对比一下类组件的写法:
class ClassComponent extends React.Component {
componentWillUnmount() {
console.log("Bye");
}
render() {
return <h1>Bye, World</h1>;
}}
函数组件和类组件各有优缺点,但函数组件相比类组件的优势:
函数组件语法更短、更简单,这使得它更容易开发、理解和测试;而类组件也会因大量使用 this而让人感到困惑
类组件过多的使用this
让整个逻辑看起来很混乱;
React团队主推的React hooks功能也只支持函数组件;
注:React团队也在努力将hooks功能引入类组件,所以没必要将现有的类组件都改写成函数组件;
类组件的性能消耗比较大,因为类组件需要创建类组件的实例,而且不能销毁。
函数式组件性能消耗小,因为函数式组件不需要创建实例,渲染的时候就执行一下,得到返回的react元素后就直接把中间量全部都销毁。
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!