一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
核心描述
- 定义:高阶组件本质就是一个函数,且该函数接受一个组件作为参数,并返回一个新的组件。高阶组件是 React 中的高级技术,用来实现重用组件逻辑。HOC 并不是 React 的 API,可以看做是 React 对装饰模式的一种实现。
- 实际应用:日志打点,可用、权限控制,双向绑定,表单校验,Redux 的 connect
- 使用方式:compose 组合多个 HOC、ES7 的 Decorators 模式写法 @xxx
- 实现方式:
- 属性代理(Props Proxy),继承 extends Component ,添加逻辑处理,并传递个被包装的组件
- 反向继承(Inheritance Inversion),继承 extends TargetComponent ,处理原组件的生命周期、props、state、render 等等
- 注意事项:
- 静态属性需要手动拷贝,可以使用:hoist-non-react-statics 包
- 传递 refs,16.3+ 版本,可用使用 forwardRef API 来传递
- 不要在 render 方法内创建高阶组件,会导致组件每次被卸载后重新挂载
- 不要改变原始组件,高阶组件就是一个没有副作用的纯函数
- 透传不相关的 props
- 设置 displayName ,方便调试,可以用 recompose 包实现
- 不要修改原始组件,使用组合组件
- 优点:
- 高阶组件就是一个没有副作用的纯函数,各个高阶组件不会互相依赖耦合
- 高阶组件也可能造成冲突,但我们可以在遵守约定的情况下避免这些行为
- 高阶组件并不关心数据使用的方式和原因,而被包裹的组件也不关心数据来自何处,高阶组件的增加不会为原组件增加负担
- 缺点:
- HOC 需要在原组件上进行包裹或者嵌套,大量使用 HOC,将会产生非常多的嵌套,会让调试变的困难
- HOC 可以劫持 props,在不遵守约定的情况下也可能造成冲突
知识拓展
-
实现 HOC 的两种模式:
- Props Proxy: HOC 对传给 WrappedComponent W 的 porps 进行操作,
- Inheritance Inversion: HOC 继承 WrappedComponent W。
-
Props Proxy
- 可以做什么:
- 操作 props
- 通过 Refs 访问到组件实例
- 提取 state
- 用其他元素包裹 WrappedComponent
- 代码示例:
function ppHOC(WrappedComponent) { return class PP extends React.Component { render() { return <WrappedComponent {...this.props}/> } } }
- 可以做什么:
-
Inheritance Inversion
- 可以做什么:
- 渲染劫持(Render Highjacking)
- 在由 render输出的任何 React 元素中读取、添加、编辑、删除 props
- 读取和修改由 render 输出的 React 元素树
- 有条件地渲染元素树
- 把样式包裹进元素树(就像在 Props Proxy 中的那样)
- 操作 state
- 渲染劫持(Render Highjacking)
- 代码示例:
function iiHOC(WrappedComponent) { return class Enhancer extends WrappedComponent { render() { return super.render() } } }
- 可以做什么:
-
举例:
- redux ,使用的是 props proxy 模式
- radium,使用的是 inheritance inversion 模式
- 过在内联样式中使用CSS 伪类增强了内联样式的能力
- 使用的是 inheritance inversion 模式
- github.com/FormidableL…
-
与 Mixin 对比
- Mixin 的作用:代码复用
- Mixin 的注意事项:只有在使用createClass来创建React组件时才可以使用,ES6 语法已废弃
- Mixin 的缺点:
- 可能会相互依赖,相互耦合,不利于代码维护
- 不同的 Mixin 中的方法可能会相互冲突
- Mixin 非常多时,组件时可以感知的,甚至还要为其做相关处理,这样会给代码造成滚雪球式的复杂性
-
与 Hooks 对比
- Hooks 的作用:16.8 +版本出现的,可以在 class 以外使用 state 和其他 React 特性,使用 Hooks 可以将在含有 state 的逻辑从组件中抽象出来,这将可以让这些逻辑容易被测试,同时可以在不重写组件结构的情况下复用这些组件。同样也可以作为一种实现状态逻辑复用的方案。
- Hooks 的注意事项:
- 只能在 React 函数式组件或者自定义 Hooks 中使用
- 不要在循环、条件、或嵌套函数中条用 Hook
- Hooks 的优点:
- 减少状态逻辑复用的风险,对比 Mixin
- 避免地狱式嵌套,对比 HOC
- 让组件更容易理解、使用函数代替 class,对比 class
参考资料
- 【官方文档】- 高阶组件:zh-hans.reactjs.org/docs/higher…
- 深入理解 React 高阶组件:zhuanlan.zhihu.com/p/24776678
浏览知识共享许可协议
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。