My App

Refs

Refs

所以,作为网页开发者,我们通常使用一组标准的 DOM 原语来构建用户界面:div、按钮、表单等。

但Web也提供了一种完全不同的绘制用户界面的方法:HTML Canvas。

如果你不熟悉,HTML Canvas 提供了一种类似“Microsoft Paint”的功能,可以通过绘制形状来创建图形。我在我的博客上使用它来创建这个有趣的“小磁屑”效果:

为了使用 HTML Canvas,我们首先渲染一个 <canvas> 标签,然后使用 JavaScript 在其上运行一系列命令。它可能看起来像这样:

const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
 
// Draw a 200 × 100 pink rectangle:
ctx.fillRect(0, 0, 200, 100);

ctx 是绘图表面。我们可以选择在 2D 或 3D(通过 webgl)中绘制。

问题是:我们如何在 React 中使用这个元素?

让我们讨论:

这是视频中的最终沙盒:

import React from 'react';

function ArtGallery() {
  // 1. Create a “ref”, a box that holds a value.
  const canvasRef = React.useRef(); // { current: undefined }

  return (
    <main>
      <div className="canvas-wrapper">
        <canvas
          // 2. Capture a reference to the <canvas> tag,
          // and put it in the “canvasRef” box.
          //
          // { current: <canvas> }
          ref={canvasRef}
          width={200}
          height={200}
        />
      </div>

      <button
        onClick={() => {
          // 3. Pluck the <canvas> tag from the box,
          // and pass it onto our `draw` function.
          draw(canvasRef.current);
        }}
      >
        Draw!
      </button>
    </main>
  );
}

function draw(canvas) {
  const ctx = canvas.getContext('2d');

  ctx.clearRect(0, 0, 200, 200);

  ctx.beginPath();
  ctx.rect(30, 90, 140, 20);
  ctx.fillStyle = 'black';
  ctx.fill();
  ctx.closePath();

  ctx.beginPath();
  ctx.arc(100, 97, 75, 1 * Math.PI, 2 * Math.PI);
  ctx.fillStyle = 'tomato';
  ctx.fill();
  ctx.closePath();

  ctx.beginPath();
  ctx.arc(100, 103, 75, 0, 1 * Math.PI);
  ctx.fillStyle = 'white';
  ctx.fill();
  ctx.closePath();
  
  ctx.beginPath();
  ctx.arc(100, 100, 25, 0, 2 * Math.PI);
  ctx.fillStyle = 'black';
  ctx.fill();
  ctx.closePath();
  ctx.beginPath();
  ctx.arc(100, 100, 19, 0, 2 * Math.PI);
  ctx.fillStyle = 'white';
  ctx.fill();
  ctx.closePath();
}

export default ArtGallery;

不仅仅是针对 DOM 节点!

由 useRef 钩子创建的 ref 对象应该被视为一个盒子。我们可以在这个盒子里存储我们想要的任何东西:DOM 节点、数字、数组、对象、函数等。

也就是说,refs 的主要用例是存储 DOM 节点。我很少需要在 ref 中存储其他任何东西。