Grund: 1. Die Syntax der Funktionskomponenten ist kürzer und einfacher, was die Entwicklung, das Verständnis und das Testen erleichtert. 2. Die übermäßige Verwendung davon in Klassenkomponenten lässt die gesamte Logik verwirrend erscheinen. 3. Die Hooks-Funktion unterstützt nur Funktionskomponenten. 4. Das React-Team hat weitere Optimierungen für Funktionskomponenten vorgenommen, um unnötige Prüfungen und Speicherverluste zu vermeiden. 5. Funktionskomponenten haben einen geringen Leistungsverbrauch, da Funktionskomponenten keine Instanzen erstellen müssen und beim Rendern ausgeführt werden, nachdem sie das zurückgegebene Reaktionselement erhalten haben , zerstören Sie direkt alle Zwischenmengen.
Die Betriebsumgebung dieses Tutorials: Windows 7-System, React18-Version, Dell G3-Computer.
Bei der Entwicklung mit dem React-Framework gibt es zwei Möglichkeiten, Komponenten zu erstellen: die Verwendung von Funktionen und die Verwendung von Klassen. Derzeit werden Funktionskomponenten immer beliebter. Im Folgenden werden anhand von Beispielen die Unterschiede zwischen Funktionskomponenten und Klassenkomponenten analysiert und die Gründe (Vorteile) für die Verwendung von Funktionskomponenten zusammengefasst.
Funktionskomponenten und Klassenkomponenten verarbeiten JSX unterschiedlich. Genau wie ihre Namen ist eine Funktionskomponente eine reine Javascript-Funktion, die JSX direkt zurückgibt; React.Component und implementieren Sie die Render-Methode, die JSX zurückgibt. Das Folgende ist ein Beispiel: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> ); }}
Das Obige definiert eine Funktionskomponente in Form einer ES6-Pfeilfunktion, und der Funktionskörper gibt JSX direkt zurück. Wenn Sie mit Pfeilfunktionen nicht vertraut sind, können Sie diese auch in der folgenden Form schreiben:
onClick={() => this.setState((state) => { return { count: state.count + 1 }; })}
Die beiden Schreibmethoden sind gleich.
Dann schauen wir uns an, wie man eine Klassenkomponente definiert. Zuerst müssen wir React.Component
erweitern und dann JSX in der Render-Methode zurückgeben. Weitere Informationen finden Sie im folgenden Codeausschnitt:
const FunctionalComponent = () => { React.useEffect(() => { console.log("Hello"); }, []); return <h1>Hello, World</h1>;};
Das Obige verwendet die destrukturierende Zuweisungssyntax von ES6, um das Modul zu importieren. Wenn Sie mit der destrukturierenden Zuweisungssyntax nicht vertraut sind, können Sie dies auch tun Schreiben Sie es in der folgenden Form, die prägnanter aussieht: 🎜🎜
class ClassComponent extends React.Component { componentDidMount() { console.log("Hello"); } render() { return <h1>Hello, World</h1>; }}
Wenn wir Daten an eine Komponente übergeben müssen, verwenden wir Requisiten, z Da <FunctionalComponent name="Shiori" /> ;
, name ein Requisitenattribut von Component ist, können hier weitere Attribute vorhanden sein. Die funktionale Form der FunctionalComponent-Komponente ist wie folgt definiert:
🎜🎜
const FunctionalComponent = () => { React.useEffect(() => { return () => { console.log("Bye"); }; }, []); return <h1>Bye, World</h1>;};🎜<p data-pid="e-i4xpLf">Oder verwenden Sie keine destrukturierende Zuweisung🎜🎜</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">class ClassComponent extends React.Component { componentWillUnmount() { console.log("Bye"); } render() { return <h1>Bye, World</h1>; }}
Bei dieser Methode müssen Sie props.name
verwenden, um das Namensattribut abzurufen. 🎜
Dann werfen wir einen Blick darauf, wie Klassenkomponenten Requisiten verwenden, 🎜🎜rrreee🎜
In Klassenkomponenten müssen Sie this verwenden
, um Requisiten abzurufen, und dann können Sie die Destrukturierungszuweisung verwenden, um das Attribut name
abzurufen. 🎜🎜🎜Umgang mit dem Zustand🎜🎜🎜
In React-Projekten müssen wir uns zwangsläufig mit Zustandsvariablen befassen. Klassenkomponenten unterstützten die Statusverarbeitung bis vor kurzem nicht. Ab React-Version 16.8 unterstützen Funktionskomponenten jedoch die Hook-Methode useState
, sodass wir Statusvariablen problemlos in Funktionskomponenten verwenden können. Im Folgenden wird ein Gegenbeispiel verwendet, um ihre Unterschiede zu veranschaulichen.
🎜🎜🎜Umgang mit Zustandsvariablen in Funktionskomponenten🎜🎜🎜rrreee🎜
Hier kommt der Hook useState
zum Einsatz, der als Parameter einen Anfangszustand erhält . In diesem Beispiel beginnt der Zähler bei 0, daher geben wir count einen Anfangswert von 0. 🎜
Der Anfangswert von state unterstützt verschiedene Datentypen, einschließlich Null-, String- oder Objektobjekte, sofern dies von Javascript zugelassen wird. Auf der linken Seite der =
-Zahl verwenden wir die Form der destrukturierenden Zuweisung, um den Rückgabewert von useState zu akzeptieren, einschließlich der aktuellen Statusvariablen und der Setter-Funktion, die die Variable aktualisiert, nämlich count
und setCount
与函数组件大同小异,首先我们要理解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元素后就直接把中间量全部都销毁。
Das obige ist der detaillierte Inhalt vonWarum React Funktionskomponenten empfiehlt. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!