在 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 反馈 — 无需本地设置。
此课程中的所有课时
- 为属性与组件返回值定义类型
- 在 TypeScript 中为事件与引用定义类型
- 泛型组件与实用工具类型
- 为 Context 与自定义钩子定义类型