網站首頁 編程語言 正文
1. 概念
高階組件和高階函數的類似,使用函數接收一個組件,并返回一個組件。
function withList(WrapComponent) {
return class extends Component {
render() {
return <div><WrapComponent {...this.props}/></div>;
}
}
};
高階組件主要用作于邏輯的封裝、攔截渲染、攔截生命周期:獲取渲染性能,日志打點等,安按照實現方式可以分為屬性代理和反向繼承兩種。
2. 屬性代理
屬性代理的作用:
- 代理props
- 條件渲染
- 添加狀態(state)
- 封裝一些通用的邏輯
2.1 代理props
function withList(WrapComponent) {
const data = [{ id: '1', text: '測試1' }, { id: '2', text: '測試2' }, { id: '3', text: '測試3' }, { id: '4', text: '測試4' }, { id: '5', text: '測試5' }]
return class extends Component {
render() {
return <div>
{this.props.data.length > 0 ? <WrapComponent {...this.props} data={data} /> : <span>{emptyText}</span>}
</div>;
}
}
};
class List extends Component {
render() {
return (
<ul>
{this.props.data.map(item => {
return <li key={item.id}>{item.text}</li>
})}
</ul>
)
}
};
export default withList(List);
2.2 條件渲染
function withList(WrapComponent, emptyText) {
return class extends Component {
render() {
return <div>
{this.props.data.length>0 ? <WrapComponent {...this.props}/> : <span>{emptyText}</span>}
</div>;
}
}
};
class List extends Component {
render() {
return (
<ul>
{this.props.data.map(item => {
return <li key={item.id}>{item.text}</li>
})}
</ul>
)
}
};
export default withList(List,'暫無數據');
2.3 添加狀態
利用這一點可以將非受控組件轉為受控組件
import React, { Component } from 'react'
class Input extends Component {
render() {
return (
<input value={this.props.value} />
)
}
};
function withInput(WrapComponent) {
return class extends Component {
state = {
value: this.props.value
}
onChange = (value) => {
this.setState({ value });
}
render() {
return <WrapComponent {...this.props} value={this.state.value} onChange={this.onChange}/>;
}
}
};
export default withInput(Input);
3. 反向繼承
- 反向繼承的作用
- 攔截渲染
- 代理props
- 劫持生命周期函數
- 操作state
- 修改react樹
3.1 攔截渲染
function withList(WrapComponent) {
return class extends WrapComponent {
render() {
return <div>
<span>通過反向繼承攔截渲染</span>
{super.render()}
</div>;
}
}
};
3.2 劫持生命周期
function withList(WrapComponent) {
return class extends WrapComponent {
componentDidMount(){
if(super.componentDidMount){
super.componentDidMount.apply(this);
};
console.log('攔截生命周期');
}
render() {
return <div>
<span>通過反向繼承攔截渲染</span>
{super.render()}
</div>;
}
}
};
3.3 操作state
import React, { Component } from 'react';
function withList(WrapComponent) {
return class extends WrapComponent {
constructor(props) {
super(props);
this.state.data = []; //將列表數據置空
}
render() {
return <div>{super.render()}</div>
}
}
};
class List extends Component {
state = {
data: [{ id: '1', text: '測試1' }, { id: '2', text: '測試2' }, { id: '3', text: '測試3' }, { id: '4', text: '測試4' }, { id: '5', text: '測試5' }],
}
render() {
return (
<ul>
{this.state.data.map(item => {
return <li key={item.id}>{item.text}</li>
})}
</ul>
)
}
};
export default withList(List);
3.4 修改react樹
import React, { Component } from 'react';
function withList(WrapComponent) {
return class extends WrapComponent {
render() {
const tree = super.render();
let newProps = { ...tree.props };
if (tree.type === 'ul') {
newProps.value = 'value';
}
return React.cloneElement(tree, newProps, newProps.children);
}
}
};
class List extends Component {
render() {
return (
<ul>
{this.props.data.map(item => {
return <li key={item.id}>{item.text}</li>
})}
</ul>
)
}
};
export default withList(List);
3.5 記錄渲染性能
function withTime(WrapComponent) {
return class extends WrapComponent {
constructor(props) {
super(props);
this.start = 0;
this.end = 0
}
componentWillMount() {
if (super.componentWillMount) {
super.componentWillMount.call(this);
};
this.start = Date.now();
}
componentDidMount() {
if (super.componentDidMount) {
super.componentDidMount.call(this);
};
this.end = Date.now();
console.log(`渲染的時間為:${(this.end - this.start) / 1000}秒`)
}
render() {
return super.render();
}
}
};
4. 使用裝飾器
4.1 安裝和配置
首先執行npm run eject暴露出webpack配置,然后安裝裝飾器插件
yarn add ?@babel/plugin-proposal-decoreators;
最后在package.json中的babel配置中添加一下配置然后重新項目
"babel": { "presets": [ "react-app" ], "plugins":[ [ "@babel/plugin-proposal-decorators", {"legacy":true} ] ] }
配置完之后如果有報紅需要配置一下:
文件-> 首選項 -> 搜索 ExperimentalDecorators 勾選上之后紅線就消失了
4.2 使用
@withList
class List extends Component {
render() {
return (
<ul>
{this.props.data.map(item => {
return <li key={item.id}>{item.text}</li>
})}
</ul>
)
}
};
5.總結
- 高階組件的作用有代復用、代理屬性、攔截渲染、劫持生命周期
- 反向繼承能直接操作和攔截組件的state和生命周期,功能比屬性代理更加強大
原文鏈接:https://blog.csdn.net/qq_44621394/article/details/127251727
相關推薦
- 2022-09-24 Go?iota關鍵字與枚舉類型實現原理_Golang
- 2023-04-24 一文掌握python中的__init__的意思及使用場景分析_python
- 2023-05-23 Django?事務回滾的具體實現_python
- 2022-02-18 Syntax Error: Error: Node Sass version 6.0.1 is in
- 2022-07-14 設置Redis最大占用內存的實現_Redis
- 2022-06-25 python數據可視化之日期折線圖畫法_python
- 2022-05-22 jQuery中的關系查找方法_jquery
- 2022-10-24 通過5個例子讓你學會Pandas中的字符串過濾_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支