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

posted @ 2021-12-23 15:40  柠檬派的奇幻漂流  阅读(370)  评论(0)    收藏  举报