React(3-2):组件进阶
组件进阶
高阶组件
前面提到的组件,都是将组件变成 UI, 而这里将会提到令一种类型的组件:高阶组件(HOC)。
高阶组件就是传入组件,返回组件的函数:
1 | const EnhancedComponent = higherOrderComponent(WrappedComponent); |
高阶组件可以做很多事情:
- 抽取重复代码
- 条件渲染
- 捕获拦截生命周期
例如,我们可以使用高阶组件来监控 props 的更新:[1]
1 | function withLogProps(WrappedComponent) { |
通常,高级组件的命名规范是 withXxxx。
动态组件
有时候,开发者希望在运行时来确定组件的类型,例如:
1 | const components = {'eat': someComponent1, 'drink': someComponent2}; |
但这种写法是不允许的。因为React 只支持
- 大写开头的变量
- 带点语法的组件:
MyComponents.DatePicker
如果需要运行时确定,则可以再定义一个大写开头的变量:
1 | const components = {'eat': someComponent1, 'drink': someComponent2}; |
如果你渲染的不是自定义组件,而是 html 元素,则可以只传一个字符串;
1 | const Com = 'a' |
再强调一下,变量名一定要首字母大写,否则 React 会将它解析成 html 元素。
引用
介绍
有时候,React 提供的常用操作可能并不能完成所有事情。例如:
audio和video的操作canvas的绘图- 一些原生的第三方库
这时候你可能需要引用原始的 DOM了。
创建引用
通常使用 React.createRef 来创建一个引用:
1 | class MyCanvas extends React.Component { |
除了使用 React.createRef,还可以使用回调函数来创建引用:
1 | class MyCanvas extends React.Component { |
使用回调函数得到的引用就是组件实例或者 DOM 对象,无需通过 .current 来访问。
1 | this.myRef.getContext("2d"); |
访问引用
当 ref 被传递给 render 中的元素时,对该节点的引用可以在 ref 的 current 属性中被访问。[2]
1 | const node = this.myRef.current; |
ref 的值根据节点的类型而有所不同:[2:1]
- 当
ref属性用于 HTML 元素时,构造函数中使用React.createRef()创建的ref接收底层 DOM 元素作为其current属性。 - 当
ref属性用于自定义的类组件时,ref对象接收组件的挂载实例作为其current属性。 - 不能在函数组件上使用
ref属性,因为他们没有实例。
下面的例子,我们创建了一个引用,来初始化一个 canvas:
1 | class Draw extends React.Component { |
转发引用
有时候,我希望通过 ref 属性获取子组件的某个 DOM 元素,例如上面 Draw 组件,我希望获取里面 canvas 的DOM。
这时候,我们就需要使用 引用转发 了。
我们通常使用 React.forwardRef 来转发引用。
先来看看函数组件。
1 | const Draw = React.forwardRef((props, ref) =>{ |
这样,通过 ref 便可以直接拿到子组件中 canvas的DOM对象了。
但有人可能有疑问:不是不能在函数组件上使用 ref 属性嘛?
实际上,引用转发将组件的引用转发给了组件内的一个元素,这样访问函数组件的 ref 就成了访问组件内元素的 ref 了。
高阶组件的转发
对一个高阶组件使用 ref 有时候会出现问题,我们来看一个栗子:
1 |
|
我们运行这个案例,发现浏览器输出的并不是 a 链接的引用,而是高级组件的引用:

这可能并不是我们想要的。我们希望高阶组件是透明的。
所以,我们可以使用转发技术来将高阶组件的 ref 进行转发。
需要注意一点: ref 不是 prop 属性。就像 key 一样,其被 React 进行了特殊处理。如果你对 HOC 添加 ref ,该 ref 将引用最外层的容器组件,而不是被包裹的组件。[1:1]
1 | function logProps(Component) { |
- 标题: React(3-2):组件进阶
- 作者: ObjectKaz
- 创建于: 2021-05-03 06:05:40
- 更新于: 2021-05-04 15:21:07
- 链接: https://www.objectkaz.cn/909bbe96590c.html
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。