React 基础巩固(二十五)——高阶组件
高阶函数
- 定义:
接收一个或多个函数作为输入
或 输出一个函数
的函数
- JS 中常用的
map
、filter
、reduce
都是高阶函数
高阶组件(Higher-Order Components, HOC)
- 定义:高阶组件是参数为函数,返回值为新组件的函数
- 高阶组件本质是函数
- 高阶组件并不是 React API 的一部分,它是基于 React 的组合特性而形成的设计模式
import React, { PureComponent } from "react";
function hoc(Cpn) {
class NewCpn1 extends PureComponent {
render() {
return <Cpn />;
}
}
return NewCpn1;
function NewCpn2(props) {}
return NewCpn2;
}
class HelloWorld extends PureComponent {
render() {
return (
<div>
<h1>hello world</h1>
</div>
);
}
}
const HelloWorldHOC = hoc(HelloWorld);
export class App extends PureComponent {
render() {
return (
<div>
<HelloWorld />
<HelloWorldHOC />
</div>
);
}
}
export default App;
高阶组件的应用场景(一)—— 用户信息增强
import React, { PureComponent } from "react";
function enhanceUserInfo(OriginCmp) {
class NewComponent extends PureComponent {
constructor() {
super();
this.state = {
userInfo: {
name: "outman",
level: 123,
},
};
}
render() {
return <OriginCmp {...this.props} {...this.state.userInfo} />;
}
}
return NewComponent;
}
export default enhanceUserInfo;
import React, { PureComponent } from "react";
import enhanceUserInfo from "./enhance_props";
const Home = enhanceUserInfo(function Home(props) {
return (
<h1>
Home: {props.name} - {props.level} - {props.age}
</h1>
);
});
const Profile = enhanceUserInfo(function Profile(props) {
return (
<h1>
Profile: {props.name} - {props.level}
</h1>
);
});
const Hello = enhanceUserInfo(function Hello(props) {
return (
<h1>
Hello: {props.name} - {props.level}
</h1>
);
});
export class App extends PureComponent {
render() {
return (
<div>
<Home age={"888"} />
<Profile />
<Hello />
</div>
);
}
}
export default App;
高阶组件的应用场景(二)—— 拦截并处理Context传参
import { createContext } from "react";
const ThemeContext = createContext();
export default ThemeContext;
- 构建 App.jsx,通过
ThemeContext.Provider
传递参数给
import React, { PureComponent } from "react";
import ThemeContext from "./context/theme_context";
import Product from "./Product";
export class App extends PureComponent {
render() {
return (
<div>
<ThemeContext.Provider value={{ color: "red", size: 18 }}>
<Product />
</ThemeContext.Provider>
</div>
);
}
}
export default App;
- 构建 Product.jsx, 在 Product 中,通过
ThemeContext.Consumer
消费参数
import React, { PureComponent } from "react";
import ThemeContext from "./context/theme_context";
export class Product extends PureComponent {
render() {
return (
<div>
Product:
<ThemeContext.Consumer>
{(value) => {
return (
<h2>
theme: {value.color} - {value.size}
</h2>
);
}}
</ThemeContext.Consumer>
</div>
);
}
}
export default Product;
- 若每次都要采用上述方式,通过
ThemeContext.Consumer
消费参数,太过繁琐。故,可以利用高阶组件进行处理。
- 构建高阶组件
with_theme
import ThemeContext from "./theme_context";
function withTheme(OriginComponent) {
return (props) => {
return (
<ThemeContext.Consumer>
{(value) => {
return <OriginComponent {...value} {...props} />;
}}
</ThemeContext.Consumer>
);
};
}
export default withTheme;
import React, { PureComponent } from "react";
import withTheme from "./context/with_theme";
export class Product extends PureComponent {
render() {
const { color, size } = this.props;
return (
<div>
Product:
{color} - {size}
</div>
);
}
}
export default withTheme(Product);
高阶组件的应用场景(三)—— 登陆鉴权
function loginAuth(OriginComponent) {
return (props) => {
const token = localStorage.getItem("token");
if (token) {
return <OriginComponent {...props} />;
} else {
return <h2>请先登陆</h2>;
}
};
}
export default loginAuth;
import React, { PureComponent } from "react";
import Cart from "./Cart";
export class App extends PureComponent {
constructor() {
super();
this.state = {
isLogin: false,
};
}
loginClick() {
localStorage.setItem("token", "test token value");
this.setState({
isLogin: true,
});
}
render() {
const { isLogin } = this.state;
return (
<div>
<button onClick={(e) => this.loginClick()}>登录</button>
<Cart />
</div>
);
}
}
export default App;
- 构建Cart.jsx,并用loginAuth包裹Cart进行鉴权处理
import React, { PureComponent } from "react";
import loginAuth from "./login_auth";
export class Cart extends PureComponent {
render() {
return (
<div>
<h2>Cart</h2>
</div>
);
}
}
export default loginAuth(Cart);
高阶组件的应用场景(四)—— 打印界面渲染时间
import { PureComponent } from "react";
function logRenderTime(OriginComponent) {
return class extends PureComponent {
UNSAFE_componentWillMount() {
this.beginTime = new Date().getTime();
}
componentDidMount() {
this.endTime = new Date().getTime();
const interval = this.endTime - this.beginTime;
console.log(`当前页面:${OriginComponent.name} 的渲染花费:${interval} ms`);
}
render() {
return <OriginComponent />;
}
};
}
export default logRenderTime
import React, { PureComponent } from 'react'
import Detail from './Detail'
export class App extends PureComponent {
render() {
return (
<div>
<Detail></Detail>
</div>
)
}
}
export default App
- 构建Detail.jsx,并通过logRenderTime拦截Detail组件,打印其界面渲染时间
import React, { PureComponent } from "react";
import logRenderTime from "./log_render_time";
export class Detail extends PureComponent {
render() {
return (
<div>
<h2>Detail Page</h2>
<ul>
<li>数据列表1</li>
<li>数据列表2</li>
<li>数据列表3</li>
<li>数据列表4</li>
<li>数据列表5</li>
<li>数据列表6</li>
<li>数据列表7</li>
<li>数据列表8</li>
<li>数据列表9</li>
<li>数据列表10</li>
</ul>
</div>
);
}
}
export default logRenderTime(Detail);