在写 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
怎么样,是不是很简单。