属性与子元素;事件处理器;引用
定义带类型的属性和子元素;安全地连接事件处理器;创建并使用引用来访问 DOM 节点。
属性与子元素;事件处理器;引用 是 CoddyKit 上的免费 TypeScript Academy 课时。 这是第 1 节课,共 3 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 TypeScript Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 TypeScript Academy 课程共包含 3 节课。
入门
目标:构建带类型的 React 组件:定义属性(包括子节点),为事件处理程序附加精确类型,并使用引用聚焦输入框。
- 带类型的属性接口
- 事件处理程序类型
- 用于访问 DOM 的引用
带类型的属性
声明一个属性接口;使用可选属性,并通过联合字面量收窄类型。将默认值放在组件内部。
import React from "react"
interface BadgeProps {
text: string
color?: "primary" | "success" | "warning"
}
export function Badge({ text, color = "primary" }: BadgeProps) {
const bg = color === "success" ? "#16a34a" : color === "warning" ? "#d97706" : "#2563eb"
return <span style={{ backgroundColor: bg, color: "white", padding: 4, borderRadius: 6 }}>{text}</span>
}
export default function App() {
return (
<div style={{ display: "grid", gap: 8 }}>
<Badge text="Saved" color="success" />
<Badge text="Warn" color="warning" />
</div>
)
}子节点
使用 PropsWithChildren<T>(或 React.PropsWithChildren)为属性添加带类型的子节点插槽。
import React, { PropsWithChildren } from "react"
type CardProps = PropsWithChildren<{ title: string }>
function Card({ title, children }: CardProps) {
return (
<div style={{ border: "1px solid #e5e7eb", padding: 12, borderRadius: 8 }}>
<h3 style={{ margin: 0 }}>{title}</h3>
<div>{children}</div>
</div>
)
}
export default function App() {
return (
<Card title="Dashboard">
<p>Children are typed automatically.</p>
</Card>
)
}事件处理程序
优先使用 React.MouseEvent<Element> 和 React.ChangeEvent<HTMLInputElement>。它们会提供带类型的 target/currentTarget。
import React from "react"
export default function App() {
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
console.log("clicked", e.currentTarget.name)
}
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
console.log("value", e.target.value)
}
return (
<div style={{ display: "grid", gap: 8 }}>
<input name="n" onChange={handleChange} placeholder="Type here" />
<button name="ok" onClick={handleClick}>Confirm</button>
</div>
)
}引用:DOM 访问
useRef<HTMLInputElement>(null) 会保留一个可为 null 的引用;请使用可选链安全地访问 DOM 节点。
import React, { useRef } from "react"
export default function App() {
const inputRef = useRef<HTMLInputElement>(null)
const focusInput = () => {
inputRef.current?.focus()
}
return (
<div style={{ display: "grid", gap: 8 }}>
<input ref={inputRef} placeholder="Focus me" />
<button onClick={focusInput}>Focus</button>
</div>
)
}转发引用
forwardRef 允许父组件访问子组件的 DOM 节点。请提供元素类型,以获得精确的类型检查。
import React, { forwardRef } from "react"
type TextInputProps = { label: string }
const TextInput = forwardRef<HTMLInputElement, TextInputProps>(function TextInput({ label }, ref) {
return (
<label style={{ display: "grid", gap: 4 }}>
<span>{label}</span>
<input ref={ref} />
</label>
)
})
export default function App() {
const setRef = (el: HTMLInputElement | null) => { if (el) el.focus() }
return <TextInput ref={setRef} label="Auto focus" />
}事件类型检查
快速检查:按钮点击处理程序的正确类型是什么?
回顾
回顾:定义属性(包括子节点),为事件指定精确类型,并使用引用(包括 forwardRef)安全地访问 DOM 节点。
常见问题解答
「属性与子元素;事件处理器;引用」课时是免费的吗?
是的 — 「属性与子元素;事件处理器;引用」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 TypeScript Academy 课程的其余内容,请升级到 CoddyKit PRO。 TypeScript Academy 课程共包含 3 节课。
「属性与子元素;事件处理器;引用」这节课中我会学到什么?
定义带类型的属性和子元素;安全地连接事件处理器;创建并使用引用来访问 DOM 节点。 你通过在浏览器中直接运行的动手代码来练习 TypeScript Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 TypeScript Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 TypeScript Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 3 节。
「属性与子元素;事件处理器;引用」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 TypeScript Academy 课中编写并运行代码吗?
能。每节 TypeScript Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 属性与子元素;事件处理器;引用
- 状态与 reducer;Context 类型
- 组件泛型——入门