0Pricing
React Academy · 课时

在 TypeScript 中为事件与引用定义类型

使用 React.ChangeEvent、React.MouseEvent 和 RefObject 泛型处理 DOM 交互。

在 TypeScript 中为事件与引用定义类型 是 CoddyKit 上的免费 React Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 React Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 React Academy 课程共包含 4 节课。

React 合成事件

React 会将原生 DOM 事件封装在 SyntheticEvent 中。每种事件类型都有对应的泛型,例如 React.ChangeEvent<HTMLInputElement>、React.MouseEvent<HTMLButtonElement> 等。

为 onChange 指定类型

最常见的事件是输入项上的 onChange。请使用 React.ChangeEvent<HTMLInputElement> 为其处理函数指定类型。

function SearchInput() {
  const [value, setValue] = useState('');

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setValue(e.target.value);
  };

  return <input value={value} onChange={handleChange} />;
}

为 onClick 指定类型

按钮点击事件使用 React.MouseEvent<HTMLButtonElement>。通过完整的类型信息,可以安全地访问 e.currentTarget、e.preventDefault() 和 e.stopPropagation()。

function DeleteButton({ onDelete }: { onDelete: () => void }) {
  const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
    e.stopPropagation();
    onDelete();
  };
  return <button onClick={handleClick}>Delete</button>;
}

为 onSubmit 指定类型

表单提交使用 React.FormEvent<HTMLFormElement>。请始终调用 e.preventDefault(),以阻止浏览器默认的页面跳转。

function LoginForm() {
  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    const form = e.currentTarget;
    const email = (form.elements.namedItem('email') as HTMLInputElement).value;
    console.log(email);
  };
  return (
    <form onSubmit={handleSubmit}>
      <input name="email" />
      <button type="submit">Login</button>
    </form>
  );
}

为键盘事件指定类型

请使用 React.KeyboardEvent<HTMLElement> 为键盘事件处理函数指定类型。这样可以安全地访问 e.key、e.code 和 e.ctrlKey。

function CommandInput() {
  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === 'Enter' && e.metaKey) {
      submitCommand();
    }
  };
  return <input onKeyDown={handleKeyDown} />;
}

使用 useRef 引用 DOM 元素

将 HTML 元素类型作为 useRef 的泛型,并将初始值设为 null。这样,TypeScript 就能知道引用保存的是该元素类型。

function AutoFocusInput() {
  const inputRef = useRef<HTMLInputElement>(null);

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

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

可变引用与 DOM 引用

存储可变值(而不是 DOM 节点)时,请使用该值而不是 null 初始化 useRef。TypeScript 随后会推断出可变的 MutableRefObject。

// DOM ref (read-only current)
const divRef = useRef<HTMLDivElement>(null);

// Mutable ref (read-write current)
const countRef = useRef<number>(0);
countRef.current += 1; // ✓ no TypeScript error

为 useImperativeHandle 指定类型

从子组件公开引用接口时,请为该接口定义一个接口,并在 forwardRef 和 useImperativeHandle 中都使用它。

interface DialogHandle {
  open: () => void;
  close: () => void;
}

const Dialog = forwardRef<DialogHandle, { title: string }>((props, ref) => {
  useImperativeHandle(ref, () => ({
    open: () => console.log('open'),
    close: () => console.log('close'),
  }));
  return <div>{props.title}</div>;
});

引用回调

引用回调会接收 DOM 元素或 null。请将其指定为 (node: HTMLElement | null) => void。

function MeasureDiv() {
  const [height, setHeight] = useState(0);

  const measuredRef = (node: HTMLDivElement | null) => {
    if (node) setHeight(node.getBoundingClientRect().height);
  };

  return <div ref={measuredRef}>Content: {height}px tall</div>;
}

事件目标与当前目标

e.target 是触发事件的元素;e.currentTarget 是附加处理函数的元素。需要特定属性时,请为 e.target 进行类型转换。

const handleClick = (e: React.MouseEvent<HTMLUListElement>) => {
  const target = e.target as HTMLLIElement;
  console.log(target.dataset.id);
};

泛型事件处理函数类型

要编写可复用的事件处理函数,请使用泛型 React.EventHandler<Event>,或者直接在行内写出完整的函数签名。

type InputChangeHandler = React.ChangeEventHandler<HTMLInputElement>;

const logChange: InputChangeHandler = (e) => {
  console.log(e.target.value); // e is fully typed
};

快速检查

对于保存 HTMLInputElement 的 useRef,应该使用哪种 TypeScript 类型?

回顾

使用 React.ChangeEvent、React.MouseEvent 和 React.FormEvent 泛型为事件处理函数指定类型。使用 useRef<HTMLElement>(null) 为 DOM 引用指定类型,并使用值的类型为可变引用指定类型。对于命令式接口,请将 forwardRef 与明确的接口结合使用。

常见问题解答

「在 TypeScript 中为事件与引用定义类型」课时是免费的吗?

是的 — 「在 TypeScript 中为事件与引用定义类型」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 React Academy 课程的其余内容,请升级到 CoddyKit PRO。 React Academy 课程共包含 4 节课。

「在 TypeScript 中为事件与引用定义类型」这节课中我会学到什么?

使用 React.ChangeEvent、React.MouseEvent 和 RefObject 泛型处理 DOM 交互。 你通过在浏览器中直接运行的动手代码来练习 React Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 React Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 React Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「在 TypeScript 中为事件与引用定义类型」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 React Academy 课中编写并运行代码吗?

能。每节 React Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 为属性与组件返回值定义类型
  2. 在 TypeScript 中为事件与引用定义类型
  3. 泛型组件与实用工具类型
  4. 为 Context 与自定义钩子定义类型
← 返回 React Academy