Refs 和 DOM

概述

在 React 中,Refs 提供了一种访问 DOM 节点或 React 元素的方式。通常情况下,我们通过状态和属性来管理组件的交互和渲染,但在某些情况下,直接操作 DOM 是必要的。Refs 允许我们在不使用状态的情况下直接与 DOM 进行交互。

为什么需要 Refs?

  1. 操作 DOM 元素:例如,聚焦输入框、触发动画、集成第三方 DOM 库等。
  2. 存储前一个状态:在某些情况下,你可能需要存储组件的前一个状态。
  3. 避免重新渲染:通过 Refs,你可以在不触发组件重新渲染的情况下访问和修改 DOM 元素。

创建 Refs

在 React 中,Refs 可以通过 React.createRef() 或 useRef() Hook 来创建。

使用 React.createRef()

import React, { Component } from 'react';

class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }

  componentDidMount() {
    this.myRef.current.focus();
  }

  render() {
    return <input ref={this.myRef} />;
  }
}

使用 useRef() Hook

import React, { useRef, useEffect } from 'react';

function MyComponent() {
  const myRef = useRef(null);

  useEffect(() => {
    myRef.current.focus();
  }, []);

  return <input ref={myRef} />;
}

访问 Refs

Refs 通过 .current 属性来访问 DOM 节点或组件实例。

const inputRef = useRef(null);

useEffect(() => {
  inputRef.current.focus();
}, []);

return <input ref={inputRef} />;

使用 Refs 的场景

1. 聚焦输入框

import React, { useRef, useEffect } from 'react';

function FocusInput() {
  const inputRef = useRef(null);

  useEffect(() => {
    inputRef.current.focus();
  }, []);

  return <input ref={inputRef} />;
}

2. 触发动画

import React, { useRef, useEffect } from 'react';

function AnimateBox() {
  const boxRef = useRef(null);

  useEffect(() => {
    boxRef.current.style.transform = 'translateX(100px)';
  }, []);

  return <div ref={boxRef} style={{ width: '100px', height: '100px', background: 'red' }} />;
}

3. 集成第三方 DOM 库

import React, { useRef, useEffect } from 'react';
import * as d3 from 'd3';

function D3Chart() {
  const chartRef = useRef(null);

  useEffect(() => {
    const svg = d3.select(chartRef.current)
      .append('svg')
      .attr('width', 500)
      .attr('height', 500);

    svg.append('circle')
      .attr('cx', 250)
      .attr('cy', 250)
      .attr('r', 50)
      .attr('fill', 'blue');
  }, []);

  return <div ref={chartRef} />;
}

实践练习

练习 1: 聚焦输入框

创建一个组件,当组件挂载时,自动聚焦到一个输入框。

import React, { useRef, useEffect } from 'react';

function AutoFocusInput() {
  const inputRef = useRef(null);

  useEffect(() => {
    inputRef.current.focus();
  }, []);

  return <input ref={inputRef} placeholder="自动聚焦" />;
}

export default AutoFocusInput;

练习 2: 触发按钮点击

创建一个按钮,当组件挂载时,自动触发按钮的点击事件。

import React, { useRef, useEffect } from 'react';

function AutoClickButton() {
  const buttonRef = useRef(null);

  useEffect(() => {
    buttonRef.current.click();
  }, []);

  return <button ref={buttonRef}>自动点击</button>;
}

export default AutoClickButton;

练习 3: 集成第三方库

使用 useRef 集成一个简单的第三方库,例如 moment.js,在组件挂载时显示当前时间。

import React, { useRef, useEffect } from 'react';
import moment from 'moment';

function CurrentTime() {
  const timeRef = useRef(null);

  useEffect(() => {
    timeRef.current.textContent = moment().format('MMMM Do YYYY, h:mm:ss a');
  }, []);

  return <div ref={timeRef} />;
}

export default CurrentTime;

总结

Refs 是 React 中一个强大的工具,允许你直接访问和操作 DOM 元素。通过 React.createRef() 或 useRef() Hook,你可以轻松地在组件中创建和使用 Refs。尽管 Refs 非常有用,但在大多数情况下,你应该优先考虑使用状态和属性来管理组件的交互和渲染。

在下一节中,我们将探讨 useState 和 useEffect Hooks,它们是 React 中管理状态和副作用的核心工具。