Refs 提供了一种方式,允许我们访问 DOM 节点或在 render 方法中创建的 React 元素。
Refs 使用场景
在某些情况下,我们需要在典型数据流之外强制修改子组件,被修改的子组件可能是一个 React 组件的实例,也可能是一个 DOM 元素,例如:
- 管理焦点,文本选择或媒体播放。
- 触发强制动画。
- 集成第三方 DOM 库。
创建 Refs
this.myRef = React.createRef();
复制代码
创建方式:
-
createRef
(支持在函数组件和类组件内部使用) -
useRef
(仅限于在函数组件内使用)使用
React.useRef()
创建Refs
,并通过ref
属性附加至React
元素上。const refContainer = useRef(initialValue); 复制代码
useRef
返回的 ref 对象在组件的整个生命周期内保持不变。
// React.useRef()与React.createRef()的区别:
import React, { useRef, useEffect, createRef, useState } from 'react';
function MyInput() {
let [count, setCount] = useState(0);
const myRef = createRef(null);
const inputRef = useRef(null);
//仅执行一次
useEffect(() => {
inputRef.current.focus();
window.myRef = myRef;
window.inputRef = inputRef;
}, []);
useEffect(() => {
//除了第一次为true, 其它每次都是 false 【createRef】
console.log('myRef === window.myRef', myRef === window.myRef);
//始终为true 【useRef】
console.log('inputRef === window.inputRef', inputRef === window.inputRef);
})
return (
<>
<input type="text" ref={inputRef}/>
<button onClick={() => setCount(count+1)}>{count}</button>
</>
)
}
复制代码
访问 Refs
当 ref 被传递给 render
中的元素时,对该节点的引用可以在 ref 的 current
属性中被访问
const node = this.myRef.current;
复制代码
ref 的值根据节点的类型而有所不同:
- 当
ref
属性用于 HTML 元素时,构造函数中使用React.createRef()
创建的ref
接收底层 DOM 元素作为其current
属性。 - 当
ref
属性用于自定义 class 组件时,ref
对象接收组件的挂载实例作为其current
属性。 - 你不能在函数组件上使用
ref
属性,因为他们没有实例。
Refs 与函数组件
默认情况下,你不能在函数组件上使用 ref
属性,因为它们没有实例。
可以在函数组件内部使用 ref
属性,只要它指向一个 DOM 元素或 class 组件
function CustomTextInput(props) {
// 这里必须声明 textInput,这样 ref 才可以引用它
const textInput = useRef(null);
function handleClick() {
textInput.current.focus();
}
return (
<div>
<input type="text" ref={textInput} />
<input type="button" value="Focus the text input" onClick={handleClick} />
</div>
);
}
复制代码
将 DOM Refs 暴露给父组件
Refs 转发
转发 refs 到 DOM 组件
Ref 转发是一项将 ref 自动地通过组件传递到其一子组件的技巧。
const FancyButton = React.forwardRef((props, ref) => (
<button ref={ref} className="FancyButton">
{props.children}
</button>
));
// 你可以直接获取 DOM button 的 ref:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;
复制代码
对上述示例发生情况的逐步解释:
- 我们通过调用 React.createRef 创建了一个 React ref 并将其赋值给 ref 变量。
- 我们通过指定 ref 为 JSX 属性,将其向下传递给 。
- React 传递 ref 给 forwardRef 内函数 (props, ref) => …,作为其第二个参数。
- 我们向下转发该 ref 参数到 ,将其指定为 JSX 属性。
- 当 ref 挂载完成,ref.current 将指向 DOM 节点。
回调 Refs
不同于传递 createRef()
创建的 ref
属性,你会传递一个函数。这个函数中接受 React 组件实例或 HTML DOM 元素作为参数,以使它们能在其他地方被存储和访问。
你可以在组件间传递回调形式的 refs,就像你可以传递通过 React.createRef()
创建的对象 refs 一样。
参考文章:
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END