React的对象式组件,以及泛型组件的应用

在写 react 的时候,用到比如 antd 等UI库,多少会遇到类似于下面这种写法

<Form.Item name="addr" label="站点地址" style={{ margin: 0 }}>
        <Input allowClear disabled={!isEditInfo} />
</Form.Item>

我们习惯了<Component {...props} />的写法,再看上面的组件,如果不了解,难免会一脸懵。其实理解了也很简单,就是万物皆对象

下面分几个步骤来实现上面Form.Item形式的组件

1. 常规组件

// 封装
class TestA extends React.Component<Props> {
  render() {
    return <div className="test-a">TestA--{this.props?.name}</div>
// 使用
export default ()=>{
  return < TestA name={'对象式组件'}  />

上面就是一个简单的react组件封装以及使用,要实现组件式,其实很简单,把封装的组件放在一个对象中就可以实现

2. 对象式封装

// 把封装的组件放到一个对象中,作为对象的属性
const Test = {
  TestA

使用的时候,就可以按预期效果来用了

// 使用
export default ()=>{
  return <Test.TestA name={'对象式组件'} />

是不是很简单。
这其实是得益于ReactJSX的语法,在reactjsx语法中一切皆对象,同时也一切皆组件,所以就有了上面的组件写法。

1. 常规组件

接着上面的组件,写一个新的组件TestB

function TestB({ name, name2 }: { name: string, name2?: string }) {
  return <div className="test-b">TestB--{name}{name2}</div>

这个组件的name属性都是指定了传参格式,如果想不指定,而是想通过传入参数的类型去推导实际类型,这就用到泛型。

2. 泛型组件

如果这个组件想用到泛型,也就是标题所说的泛型组件,其实也很简单

function TestB<T>({ name, name2 }: { name: T, name2?: T }) {
  return <div className="test-b">TestB--{name}{name2}</div>

想上面一样,只要给组件TestB一个类型参数,后面用到的同一个类型变量,就会根据传入的参数类型自动推导,这就是泛型。

比如我给组件TestB指定一个类型type TestType = string,使用的时候如下

export default ()=>{
  return <TestB<TestType>
        name2={undefined} // name2 的类型同样是由 TestType 决定,因为 name2 是可选属性,所以可以为 undefined
        name={'组件上使用泛型'}

上面的<TestType>就是相当于给组件TestB指定了传入的props都只能用string
有一点需要注意的是,TestType在这里不能用对象类型声明或者接口声明,否则只能如下面那样使用

interface TestType {
  name: string
  name2: number | undefined
export default ()=>{
     return <Test.TestB<TestType>
        name2={undefined} // name2 的类型同样是由 TestType 决定,因为 name2 是可选属性,所以可以为 undefined
        name={{
          name: '组件上使用泛型',
          name2: 123

怎么样,是不是很简单。