0Pricing
TypeScript Academy · 课时

属性与子元素;事件处理器;引用

定义带类型的属性和子元素;安全地连接事件处理器;创建并使用引用来访问 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 反馈 — 无需本地设置。

此课程中的所有课时

  1. 属性与子元素;事件处理器;引用
  2. 状态与 reducer;Context 类型
  3. 组件泛型——入门
← 返回 TypeScript Academy