1、Refs是什么?
官网Refs解释:Refs 提供了一种方式,允许我们访问DOM 节点或render 方法创建的 React 元素。
2、什么时候使用refs?
1) 管理焦点,文本选择或媒体播放。
对于聚焦和失去焦点,下面举例说明
//原文链接:https://stackoverflow.com/questions/32553158/detect-click-outside-react-component
1 import React, { Component } from 'react';
2 import PropTypes from 'prop-types';
3
4 /**
5 * Component that alerts if you click outside of it
6 */
7 export default class OutsideAlerter extends Component {
8 constructor(props) {
9 super(props);
//使用 React.createRef() 创建Refs
11 this.wrapperRef = React.createRef();
12 this.setWrapperRef = this.setWrapperRef.bind(this);
13 this.handleClickOutside = this.handleClickOutside.bind(this);
14 }
15
16 componentDidMount() {
//只有在组件挂载时才会给current属性传入dom元素
17 document.addEventListener('mousedown', this.handleClickOutside);
18 }
19 //在组件卸载时给current属性传入null值
20 componentWillUnmount() {
21 document.removeEventListener('mousedown', this.handleClickOutside);
22 }
23
24 /**
25 * Alert if clicked on outside of element
26 */
27 handleClickOutside(event) {
//此时可以通过创建的Refs的current属性来访问底层dom元素节点(原生dom)
//当ref属性用于自定义的class组件时,current属性访问的是该组件的挂载实例(此处可以参考下面内容的第四点
28 if (this.wrapperRef.current && !this.wrapperRef.current.contains(event.target)) {
29 alert('You clicked outside of me!');
30 }
31 }
33 render() {
//通过ref属性将创建的Refs即wrapperRef附加到HTML元素
34 return <div ref={this.wrapperRef}>{this.props.children}</div>;
35 }
36 }
37
38 OutsideAlerter.propTypes = {
39 children: PropTypes.element.isRequired,
40 };
2)触发强制动画。
3)集成第三方 DOM 库。
3、Refs都包含的属性
ref可以调用的属性:current
此时的current就是指Refs访问到的原生dom节点
current可以调用的属性和方法:
如果是访问html元素,此时可以调用原生DOM事件
如果是自定义的class组件,可以直接调用该类组件中的属性或者成员方法
contains()方法:判断某个元素是不是选定元素的子元素或者本身
例如,在实际开发中,要求点击安全域以外的空白地方,实现隐藏当前面板的效果
this.toggleContainer.current.contains(event.target) 具体代码
4、ref 的值根据节点的类型而有所不同,此时可以参考react官网中关于Refs属性讲解
- 当 ref 属性用于 HTML 元素时,构造函数中使用 React.createRef() 创建的 ref 接收底层 DOM 元素作为其 current 属性。
此时可以通过Refs的current属性直接调用原生dom可以触发的事件(原生DOM事件) - 当 ref 属性用于自定义 class 组件时,ref 对象接收组件的挂载实例作为其 current 属性。
此时可以通过ref来访问该类组件中的属性或者成员方法 - 默认情况下,你不能在函数组件上使用 ref 属性,因为它们没有实例:
5、高阶组件中的Refs
参考链接:https://juejin.cn/post/6844903809274085389
// 记录状态值变更操作
function logProps(Comp) {
class LogProps extends React.Component {
componentDidUpdate(prevProps) {
console.log('old props:', prevProps);
console.log('new props:', this.props);
}
render() {
const { forwardedRef, ...rest } = this.props;
return <Comp ref={ forwardedRef } {...rest} />;
}
}
return React.forwardRef((props, ref) => {
return <LogProps { ...props } forwardedRef={ ref } />;
});
}
// 子组件
const BtnComp = React.forwardRef((props, ref) => {
return (
<div>
<button ref={ref} className='btn'>
{ props.children }
</button>
</div>
)
});
// 被logProps包装后返回的新子组件
const NewBtnComp = logProps(BtnComp);
class TestComp extends React.Component {
constructor(props) {
super(props);
this.btnRef = React.createRef();
this.state = {
value: '初始化'
}
}
componentDidMount() {
console.log('ref', this.btnRef);
console.log('ref', this.btnRef.current.className);
this.btnRef.current.classList.add('cancel'); // 给BtnComp中的button添加一个class
this.btnRef.current.focus(); // focus到button元素上
setTimeout(() => {
this.setState({
value: '更新'
});
}, 10000);
}
render() {
return (
//btnRef
<NewBtnComp ref={this.btnRef}>{this.state.value}</NewBtnComp>
);
}
}