目录监介使用HOC的原因HOC的实现方式属性代理反向继承属性代理和反向继承对比监介 高阶组件也就是我们常说的HOC,是React中用于复用组件逻辑的一种高级技巧。HOC自身不是Rea
高阶组件也就是我们常说的HOC,是React中用于复用组件逻辑的一种高级技巧。HOC自身不是React api的一部分,他是一种基于React的组合特性而形成的设计模式。
其实就是组件作为参数,返回值也是组件的函数,他是纯函数,不会修改传入的组件,也不会使用继承来复制其行为。相反,HOC通过将组件包装在容器组件中来组成新组件。HOC是纯函数,没有副作用。
先来看一个简单的HOC实现方式
function withLog(Component) {
return function (props) {
console.log(`[${new Date().toISOString()}] ${Component.name} props:`, props);
return <Component {...props} />;
};
}
这个HOC接收一个组件作为参数,返回一个新的组件,新的组件在渲染之前会先输出当前时间和传入的组件的名称和props到控制台,然后再将props传递给原始组件进行渲染。
使用这个HOC可以像下面这样
function MyComponent(props) {
return <div>{props.message}</div>;
}
const MyComponentWithLog = withLog(MyComponent);
ReactDOM.render(
<MyComponentWithLog message="Hello, world!" />,
document.getElementById('root')
);
渲染的时候控制台会输出
[2023-04-16T00:00:00.000Z] MyComponent props: { message: "Hello, world!" }
可以看到,HOC 可以用来增强组件的功能,比如添加日志、添加权限校验、添加数据预处理等。
其实HOC的实现方式主要分为两种:属性代理和反向继承
使用组合的方式,将组件包装在容器上,依赖父子组件的生命周期关系来:
操作props
// 可以通过属性代理,拦截父组件传递过来的porps并进行处理。
// 返回一个无状态的函数组件
function HOC(WrappedComponent) {
const newProps = { type: 'HOC' };
return props => <WrappedComponent {...props} {...newProps}/>;
}
// 返回一个有状态的 class 组件
function HOC(WrappedComponent) {
return class extends React.Component {
render() {
const newProps = { type: 'HOC' };
return <WrappedComponent {...this.props} {...newProps}/>;
}
};
}
抽象state
通过属性代理无法直接操作原组件的state,可以通过props和回调函数抽象state
function HOC(WrappedComponent) {
return class extends React.Component {
constructor(props) {
super(props);
this.state = {
name: '',
};
this.onChange = this.onChange.bind(this);
}
onChange = (event) => {
this.setState({
name: event.target.value,
})
}
render() {
const newProps = {
name: {
value: this.state.name,
onChange: this.onChange,
},
};
return <WrappedComponent {...this.props} {...newProps} />;
}
};
}
// 使用
@HOC
class Example extends Component {
render() {
return <input name="name" {...this.props.name} />;
}
}
这里我们稍微做一下解释。我们主要的目的是想通过传给HOC的这个组件来修改HOC的state,在HOC中定义了onChange方法目的是可以修改state。如果在WrappedComponent中调用onChange方法呢?我们可以定义一个对象作为WrappedComponent的props,然后将onChange方法存储在定义的对象上,传给WrappedComponent。
在WrappedComponent中,我们定义了一个input,我们都知道input有value属性作为input的值,还有一个onChange方法作为change事件,我们把传给WrappedComponent的props结构刚好就是value和onChange。这样当input在change的时候就可以就修改state的值了。
通过props实现条件渲染
通过props来控制是否渲染及传入数据
import * as React from 'react';
function HOC (WrappedComponent) {
return (props) => (
<div>
{
props.isshow ? (
<WrappedComponent
{...props}
/>
) : <div>暂无数据</div>
}
</div>
);
}
export default HOC;
其他元素wrapper传入的组件
function withBackgroundColor(WrappedComponent) {
return class extends React.Component {
render() {
return (
<div style={{ backgroundColor: '#ccc' }}>
<WrappedComponent {...this.props} {...newProps} />
</div>
);
}
};
}
使用一个函数接收一个组件作为参数传入,并返回一个继承了该传入组件的类组件,且在返回组件的render()
方法中返回了super.render()
方法。
const HOC = (WrappedComponent) => {
return class extends WrappedComponent {
render() {
return super.render()
}
}
}
render.super()
获取传入组件的render,可以有选择的渲染劫持function HOC(WrappedComponent){
const didMount = WrappedComponent.prototype.componentDidMount;
// 继承了传入组件
return class HOC extends WrappedComponent {
async componentDidMount(){
// 劫持 WrappedComponent 组件的生命周期
if (didMount) {
await didMount.apply(this);
}
...
}
render(){
//使用 super 调用传入组件的 render 方法
return super.render();
}
}
}
读取/操作原组件的state
function HOC(WrappedComponent){
const didMount = WrappedComponent.prototype.componentDidMount;
// 继承了传入组件
return class HOC extends WrappedComponent {
async componentDidMount(){
if (didMount) {
await didMount.apply(this);
}
// 将 state 中的 number 值修改成 2
this.setState({ number: 2 });
}
render(){
//使用 super 调用传入组件的 render 方法
return super.render();
}
}
}
通过this.setState({ number: 2 });
修改了原组件WrappedComponent
中的state的number值
条件渲染
const HOC = (WrappedComponent) =>
class extends WrappedComponent {
render() {
if (this.props.isRender) {
return super.render();
} else {
return <div>暂无数据</div>;
}
}
}
修改react树
// 修改返回render结果
function HigherOrderComponent(WrappedComponent) {
return class extends WrappedComponent {
render() {
const tree = super.render();
const newProps = {};
if (tree && tree.type === 'input') {
newProps.value = 'something here';
}
const props = {
...tree.props,
...newProps,
};
const newTree = React.cloneElement(tree, props, tree.props.children);
return newTree;
}
};
}
这里首先通过super.render()
拿到需要渲染的树,然后对这个渲染树做了修改。比如如果是一个input,则修改它的value值。
到此这篇关于React用法之高阶组件的用法详解的文章就介绍到这了,更多相关React高阶组件内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
--结束END--
本文标题: React用法之高阶组件的用法详解
本文链接: https://www.lsjlt.com/news/210020.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-01-12
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0