React里的Ref访问Dom元素
与Vue相似,React也有一个ref可以用来访问某个Dom元素
class MyComponent extends React.Component { constructor(props) { super(props); this.myRef = React.createRef(); } render() { return <div ref={this.myRef} />; } }
1.访问 Refs
当 ref 被传递给 render
中的元素时,对该节点的引用可以在 ref 的 current
属性中被访问。
const node = this.myRef.current;
- 当
ref
属性用于 HTML 元素时,构造函数中使用React.createRef()
创建的ref
接收底层 DOM 元素作为其current
属性。 - 当
ref
属性用于自定义 class 组件时,ref
对象接收组件的挂载实例作为其current
属性。 - 你不能在函数组件上使用
ref
属性,因为他们没有实例。
注意:React 会在组件挂载时给 current
属性传入 DOM 元素,并在组件卸载时传入 null
值。ref
会在 componentDidMount
或 componentDidUpdate
生命周期钩子触发前更新。
2. 如何让函数式组件使用Ref呢?
使用useRef、useImperativeHandle、forwardRef来实现
3.useRef
使用useRef来返回一个可变、可读写的ref对象,其 .current
属性被初始化为传入的参数(initialValue
)。返回的 ref 对象在组件的整个生命周期内保持不变。
const textInput = useRef(null);
你应该熟悉 ref 这一种访问 DOM 的主要方式。如果你将 ref 对象以 <div ref={myRef} />
形式传入组件,则无论该节点如何改变,React 都会将 ref 对象的 .current
属性设置为相应的 DOM 节点。
请记住,当 ref 对象内容发生变化时,useRef
并不会通知你。变更 .current
属性不会引发组件重新渲染。如果想要在 React 绑定或解绑 DOM 节点的 ref 时运行某些代码,则需要使用回调 ref 来实现。
4.useImperativeHandle
useImperativeHandle(ref, createHandle, [deps])
useImperativeHandle
可以让你在使用 ref
时自定义暴露给父组件的实例值。在大多数情况下,应当避免使用 ref 这样的命令式代码。useImperativeHandle
应当与 forwardRef
一起使用:
具体可以查看react官方文档的Hook API章节,地址如下:https://react.docschina.org/docs/hooks-reference.html#useimperativehandle
5.forwardRef
React.forward 主要用于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>;
这样,使用 FancyButton
的组件可以获取底层 DOM 节点 button
的 ref ,并在必要时访问,就像其直接使用 DOM button
一样。
以下是对上述示例发生情况的逐步解释:
- 我们通过调用
React.createRef
创建了一个 React ref 并将其赋值给ref
变量。 - 我们通过指定
ref
为 JSX 属性,将其向下传递给<FancyButton ref={ref}>
。 - React 传递
ref
给forwardRef
内函数(props, ref) => ...
,作为其第二个参数。 - 我们向下转发该
ref
参数到<button ref={ref}>
,将其指定为 JSX 属性。 - 当 ref 挂载完成,
ref.current
将指向<button>
DOM 节点。
具体用法可以看react官网《Refs转发》篇章,地址为https://react.docschina.org/docs/forwarding-refs.html#forwarding-refs-to-dom-components。
整理一下代码:
export default function App() { const counterRef = useRef(); function reset() { counterRef.current?.resetCount(); } return ( <div style={{ padding: 10 }}> <button onClick={reset}>reset</button> <MyCounter ref={counterRef} /> </div> ); } /** -------------------------------------- */ function Counter(props, ref) { const [count, setCount] = useState(0); useImperativeHandle(ref, () => ({ resetCount: resetCount, })); function resetCount() { setCount(0); } function increment() { setCount(count + 1); } return ( <div> <hr /> <span>{count}</span> <button onClick={increment}>+1</button> </div> ); } const MyCounter = React.forwardRef(Counter);
代码来自CSDNhttps://blog.csdn.net/sinat_34693148/article/details/112913016。