用 ts 开发 react 组件
基础函数式组件
不用传递任何的 prop,直接返回一个 jsx 作为 react 组件
1 2 3
| function Title() { return <h1>Welcome to this application</h1>; }
|
带有 prop 的函数式组件
声明 props 类型并将 prop 传递给 jsx
1 2 3 4 5 6 7
| type GreetingProps = { name: string; };
function Greeting(props: GreetingProps) { return <p>Hi {props.name} 👋</p> }
|
对 prop 进行解构或许可读性更好
1 2 3
| function Greeting({ name }: GreetingProps) { return <p>Hi {name} 👋</p>; }
|
假如 GreetingProps 中的 name 可选,那么就要给 name 一个默认值,以防 name 会变成 undefined
1 2 3 4 5 6 7
| type LoginMsgProps = { name?: string; };
function LoginMsg({ name = "Guest" }: LoginMsgProps) { return <p>Logged in as {name}</p>; }
|
Children
对于 children,更倾向于显示定义,而对于 ReactNode 类型来说,已经能够接受大多数的东西,比如 jsx,string 字符串等等
1 2 3 4 5 6 7 8 9 10 11 12 13
| type CardProps = { title: string; children: React.ReactNode; };
export function Card({ title, children }: CardProps) { return ( <section className="cards"> <h2>{title}</h2> {children} </section> ); }
|
当不需要 children 元素时,可以显示定义 children 的类型为 never
1 2 3 4
| type SaveButtonProps = {
children: never }
|
这样当传递了 children 时就会抛出错误
对 html 元素使用拓展符
拓展符对于 html 元素来说是个很好的特性,因为它能帮助你确保你把所有的 html 属性都给挪到你需要的元素上
1 2 3 4 5
| type ButtonProps = JSX.IntrinsicElements["button"];
function Button({ ...allProps }: ButtonProps) { return <button {...allProps} />; }
|
属性可以自定义设计
当需要对 html 某些属性进行约束时,可以对它们进行自定义设定
如下这个例子,对 type 进行类型约束,这样仅能被赋予"primary" | "secondary"
这两个值了
1 2 3 4 5 6 7 8 9 10
| type StyledButton = Omit< JSX.IntrinsicElements["button"], "type" | "className" > & { type: "primary" | "secondary"; };
function StyledButton({ type, ...allProps }: StyledButton) { return <Button className={`btn-${type}`} />; }
|
Required
为了防止被 omit 出来的属性会忘记进行添加,封装一个 helper 来进行约束,
1 2
| type MakeRequired<T, K extends keyof T> = Omit<T, K> & Required<{ [P in K]: T[P] }>;
|
这样既可以将需要约束的属性omit出来,同时还能够防止忘记添加被omit出来的属性
1 2 3 4 5 6 7 8 9 10 11
| type ImgProps = MakeRequired< JSX.IntrinsicElements["img"], "alt" | "src" >;
export function Img({ alt, ...allProps }: ImgProps) { return <img alt={alt} {...allProps} />; }
const zz = <Img alt="..." src="..." />;
|