1. 函数式组件和类组件区别
- 函数式组件
函数式组件是一种简单的组件定义方式,它是一个以JavaScript函数为基础的组件。
可以把函数式组件理解为纯函数,它的输入为props,输出为JSX。函数式组件没有状态,也没有生命周期。
function List(props){
const {
list} = this.props
return <ul>
{
list.map((item, index) => {
return <li key={
item.id}>
<span>{
item.title}</span>
</li>
})
}
</ul>
}
- 类组件
类组件是React中的早期概念,它通过继承React.Component类来创建。类组件在React的生命周期和状态管理方面具有更多的控制权。
class List extends React.Component{
constructor(props){
super(props)
}
render(){
const {
list} = this.props
return <ul>
{
list.map((item, index) => {
return <li key={
item.id}>
<span>{
item.title}</span>
</li>
})
}
</ul>
}
}
2. 非受控组件
非受控组件:通过在组件在传入ref属性,然后通过ref属性拿到当前组件的DOM节点,通过DOM节点拿到当前组件的值。通过这种方式拿到的组件的值,是不受组件的状态控制的。这种组件称为“非受控组件”。
- 以下代码示例中,alert中的提示信息为input标签DOM元素中的值,而不是状态中的值。
class App extends React.Component{
constructor(props) {
super(props)
this.state = {
name: '小白',
}
this.nameInputRef = React.createRef() // 通过React.createRef()方法创建ref
}
alertName = () => {
const elem = this.nameInputRef.current // 通过 ref 获取 DOM 节点
alert(elem.value) // 不是state的值,而是从DOM元素中取得的值
}
render(){
return(
<div>
<input defaultValue={
this.state.name} ref={
this.nameInputRef}/>
<span>state.name: {
this.state.name}</span>
<br/>
<button onClick={
this.alertName}>alert name</button>
</div>
)
}
}
- 非受控组件的使用场景:必须手动操作DOM元素,只更改组件的状态无法实现目的。例如文件上传,因为文件的相关信息必须通过DOM元素的
files
属性获取。
class App extends React.Component{
constructor(props) {
super(props)
this.fileInputRef = React.createRef() // 通过React.createRef()方法创建ref
}
alertFile = () => {
const elem = this.fileInputRef.current // 通过 ref 获取 DOM 节点
alert(elem.files[0].name) // 打印上传的文件的名字
}
render(){
return(
<div>
<input type="file" ref={
this.fileInputRef}/>
<button onClick={
this.alertFile}>alert file</button>
</div>
)
}
}
3. Portals
React 中的 Portals(传送门)是一种高级特性,允许你将子组件渲染到父组件的 DOM 层次结构之外的位置,能够更灵活地管理组件的渲染位置。这对于在 React 应用程序中处理一些特殊的 UI 需求非常有用,例如在模态框、弹出窗口或全局组件中显示内容。
React 组件通常会将它们的输出渲染到它们的父组件的DOM中。但是使用 Portals,可以将子组件渲染到应用程序的DOM层次结构之外的位置。这使得你可以在应用程序的不同部分渲染内容,而不受父组件的约束。
通过 ReactDOM.createPortal()
方法实现Portals,该方法接受两个参数:1. 要渲染的React元素; 2. 目标DOM节点;
ReactDOM.createPortal(
<ChildComponent />,
document.getElementById('portal-root')
);
上述代码,将<ChildComponent/>
组件渲染到 id="portal-root"
的DOM节点之外的位置。
4. context
5. 异步组件
在React框架中,当应用程序变得复杂时,通过使用异步加载组件的技术在需要时加载必要的组件,可以减少初始加载时间并提高应用程序性能。通常使用React.lazy()
和import()
的组合来实现异步加载组件。
使用 React.lazy()
创建异步组件:使用 React.lazy()
函数来创建异步加载的组件。这个函数接受一个函数,这个函数返回一个动态 import()
调用的结果,该调用加载组件的模块。
const AsyncComponent = React.lazy(() => import('./AsyncComponent'));
异步加载组件需要时间,因此在组件加载期间,可以显示一个loading。使用 Suspense
组件来包装异步组件,在 Suspense
组件中设置 fallback
属性来定义加载过程中显示的内容。
import React, {
Suspense } from 'react';
const AsyncComponent = React.lazy(() => import('./AsyncComponent'));
function App() {
return (
<div>
<Suspense fallback={
<div>Loading...</div>}>
<AsyncComponent />
</Suspense>
</div>
);
}
上述代码中,当AsyncComponent
组件在加载时,会渲染Loading...
元素。