props
React 元素为用户自定义组件时,它会将 JSX 中所接收的所有属性集中转换为单个对象传递给组件,这个对象就是props
。例如上面示例中定义的组件Shelf
在使用时就可以如下传递其中展示所需的props.books
。props
所提供的主要功能就是父子组件之间的通信,允许父组件将任意合法的 Javascript 内容,例如字面量、对象、数组、函数等传递给子组件。
一个组件所接收到的props
内容在组件的逻辑处理和组件渲染期间是只读的不可更改的。
在定义组件的props
时,我们往往会为其定义一套类型来方便规定组件可以接收的属性。例如可以这样做。
// 使用type定义
type BookProps = {
code: string;
title: string;
description?: string;
recommended?: boolean;
onSelect?: (code: string) => void;
};
//使用interface定义
interface BookProps {
code: string;
title: string;
description?: string;
recommended?: boolean;
onSelect?: (code: string) => void;
}
就像上面示例中所列举的,如果使用 Typescript 来定义props
参数的类型,是可以使用type
定义一个类型或者使用interface
定义一个接口的。这两种定义出来的props
内容是没有区别的,区别仅在于在 Typescript 语言中type
和 interface
的区别。
在Typescript中,interface
定义的接口默认是会自动拼合所有同名接口的,但type
定义的类型则不支持重名,而且type
还支持定义联合类型等更复杂的类型。所以在实际使用中,可以根据业务的实际需要来选择使用哪种方式,在这一点上,React和Typescript都没有做具体的规定。
在上面这个示例定义的props
类型中,在使用的时候,可以像下面这样来使用。
<Book
code="ISBN-839485"
title="Live with React"
recommended
onSelect={(code) => console.debug("Selected Book: ", code)}
/>
在上面这个示例中,没有向组件Book
中传递属性description
,而且props
类型中description
定义的是可选属性,那么在组件中这个属性的取值就默认是undefined
了。对于布尔类型的属性,如果其出现在了组件的属性列表中,但没有给定值,例如上面示例中的recommended
,那么在组件中它的值就是true
。这也算是 React 提供的一个特性之一。
给子组件传递props
就跟在 HTML 中为标签元素设定属性一样。只是需要注意的是,如果传递的内容是使用""
包裹的,那么传递的内容将是一个字面量,如果是使用{}
包裹的,那么传递的内容将是一个对象或者数组。
在组件中接收props
的时候,还常常利用 Javascript 中的解构语法来简化props
中内容的调用,例如上面这个示例中,<Book>
组件就可以这样定义。
function Book({
code,
title,
description,
// 可以利用赋予默认值的方式,来设置其中某个未提供属性的默认值
recommended = false,
onSelect,
}: BookProps) {
return (
<div>
<h1>{title}</h1>
<span>{code}</span>
</div>
);
}
children
属性的传递
children
属性在 React 中负责传递包裹在当前组件中的子元素。例如在下面这个用法中,<Child>
组件就是以<Parent>
组件的子组件身份出现的。
<Parent>
<Child />
</Parent>
要在组件中获取到传递进来的children
属性,也是通过props
参数的。例如以下就是<Parant>
组件的定义示例。
function Parent(props) {
return <div>{props.children}</div>;
}
但是在定义props
的类型的时候,却不必特意手动定义children
属性,因为 React 提供了一个默认的接口PropsWithChildren
来提供这个属性。其具体使用可以参考以下示例。
import { PropsWithChildren } from "react";
interface ParentProps {
name: string;
}
export function Parent(props: PropsWithChildren<ParentProps>) {
return (
<div>
<h1>{props.name}</h1>
{props.children}
</div>
);
}
利用 React 中提供的这个接口可以很方便的给当前定义的props
类型中增加children
属性。