Javascript 在TypeScript中对函数组件使用点表示法
ReactJs官方文档建议按照与库类似的步骤创建组件:Javascript 在TypeScript中对函数组件使用点表示法,javascript,reactjs,typescript,Javascript,Reactjs,Typescript,ReactJs官方文档建议按照与库类似的步骤创建组件: 卡片标题 一些快速的示例文本构建在卡片标题上,并构成大部分 卡片的内容。 多亏了,我知道我可以使用javascript中的功能组件创建此结构: const Card=({children})=>{children} 常量体=()=>体 Card.Body=Body 导出默认卡 使用TypeScript,我决定向其中添加相应的类型: const-Card:React.FunctionComponent=({children}):JSX.
卡片标题
一些快速的示例文本构建在卡片标题上,并构成大部分
卡片的内容。
多亏了,我知道我可以使用javascript中的功能组件创建此结构:
const Card=({children})=>{children}
常量体=()=>体
Card.Body=Body
导出默认卡
使用TypeScript,我决定向其中添加相应的类型:
const-Card:React.FunctionComponent=({children}):JSX.Element=>{children}
const Body:React.FunctionComponent=():JSX.Element=>Body
Card.Body=Body/const-Card:React.FunctionComponent&{Body:React.FunctionComponent}=({children}):JSX.Element=>{children}
const Body:React.FunctionComponent=():JSX.Element=>Body
卡体=卡体;
或更具可读性:
type BodyComponent = React.FunctionComponent;
type CardComponent = React.FunctionComponent & { Body: BodyComponent };
const Card: CardComponent = ({ children }): JSX.Element => <>{children}</>;
const Body: BodyComponent = (): JSX.Element => <>Body</>;
Card.Body = Body;
类型BodyComponent=React.FunctionComponent;
类型CardComponent=React.FunctionComponent&{Body:BodyComponent};
const Card:CardComponent=({children}):JSX.Element=>{children};
const Body:BodyComponent=():JSX.Element=>Body;
卡体=卡体;
在花了大量时间研究如何在forwardRef
组件中使用点表示法之后,这是我的实现:
卡体组件:
export const CardBody = forwardRef<HTMLDivElement, CardBodyProps>(({ children, ...rest }, ref) => (
<div {...rest} ref={ref}>
{children}
</div>
));
//Not necessary if Bonus feature wont be implemented
CardBody.displayName = "CardBody";
interface CardComponent extends React.ForwardRefExoticComponent<CardProps & React.RefAttributes<HTMLDivElement>> {
Body: React.ForwardRefExoticComponent<CardBodyProps & React.RefAttributes<HTMLDivElement>>;
}
const Card = forwardRef<HTMLDivElement, CardProps>(({ children, ...rest }, ref) => (
<div {...rest} ref={ref}>
{children}
</div>
)) as CardComponent;
Card.Body = CardBody;
export default Card;
export const CardBody=forwardRef(({children,…rest},ref)=>(
{儿童}
));
//如果奖金功能无法实现,则不需要
CardBody.displayName=“CardBody”;
卡组件:
export const CardBody = forwardRef<HTMLDivElement, CardBodyProps>(({ children, ...rest }, ref) => (
<div {...rest} ref={ref}>
{children}
</div>
));
//Not necessary if Bonus feature wont be implemented
CardBody.displayName = "CardBody";
interface CardComponent extends React.ForwardRefExoticComponent<CardProps & React.RefAttributes<HTMLDivElement>> {
Body: React.ForwardRefExoticComponent<CardBodyProps & React.RefAttributes<HTMLDivElement>>;
}
const Card = forwardRef<HTMLDivElement, CardProps>(({ children, ...rest }, ref) => (
<div {...rest} ref={ref}>
{children}
</div>
)) as CardComponent;
Card.Body = CardBody;
export default Card;
接口CardComponent扩展React.ForwardRefExoticComponent{
主体:React.ForwardRefExoticComponent;
}
const Card=forwardRef({children,…rest},ref)=>(
{儿童}
))作为组件;
Card.Body=CardBody;
导出默认卡;
在您的代码中使用它看起来像这样:
<Card ref={cardRef}>
<Card.Body ref={bodyRef}>
Some random body text
</Card.Body>
</Card>
一些随机正文
我发现了一种使用Object.assign
的简洁方法,可以使点符号与ts一起工作
type TableCompositionType = {
Head: TableHeadComponentType;
Body: TableBodyComponentType;
Row: TableRowComponentType;
Column: TableColumnComponentType;
};
type TableType = TableComponentType & TableCompositionType;
export const Table: TableType = TableComponent;
Table.Head = TableHeadComponent;
Table.Body = TableBodyComponent;
Table.Row = TableRowComponent;
Table.Column = TableColumnComponent;
ts会抛出错误的地方。我的基本工作解决方案是:
export const Table: TableType = Object.assign(TableComponent, {
Head: TableHeadComponent,
Body: TableBodyComponent,
Row: TableRowComponent,
Column: TableColumnComponent,
});
唯一的缺点是,虽然将对结果进行类型检查,但对象参数中的各个子组件将不会被检查,这可能有助于调试
一个好的做法是预先定义(和类型检查)参数
const tableComposition: TableCompositionType = {
Head: TableHeadComponent,
Body: TableBodyComponent,
Row: TableRowComponent,
Column: TableColumnComponent,
};
export const Table: TableType = Object.assign(TableComponent, tableComposition);
但由于Object.assign
是泛型的,因此这也是有效的:
export const Table = Object.assign<TableComponentType, TableCompositionType>(TableComponent, {
Head: TableHeadComponent,
Body: TableBodyComponent,
Row: TableRowComponent,
Column: TableColumnComponent,
});
对于纯React功能组件,我是这样做的:
import React, {FC} from 'react';
interface TextProps {
label: 'string'
}
const Text: FC<TextProps> = ({label}: TextProps) => {
return (
<input
/>
)
};
export default Text;
如何使用
import React, {FC} from 'react';
import {Charts, Inputs} from 'components';
const App: FC = () => {
return (
<>
<Inputs.Text/>
<Inputs.Slider/>
<Charts.Line/>
</>
)
};
export default App;
代码
import React, {FC} from 'react';
import {Charts, Inputs} from 'components';
const App: FC = () => {
return (
<>
<Inputs.Text/>
<Inputs.Slider/>
<Charts.Line/>
</>
)
};
export default App;
最后一个组件,如Text.tsx
,应该如下所示:
import React, {FC} from 'react';
interface TextProps {
label: 'string'
}
const Text: FC<TextProps> = ({label}: TextProps) => {
return (
<input
/>
)
};
export default Text;
src/components/Inputs/index.tsx
export {default as Charts} from './Charts';
export {default as Inputs} from './Inputs';
import {Text, Slider} from './components'
const Inputs = {
Text,
Slider
};
export default Inputs;
export {default as Text} from './Text';
export {default as Slider} from './Slider';
export {default} from './Text';
src/components/Inputs/components/index.tsx
export {default as Charts} from './Charts';
export {default as Inputs} from './Inputs';
import {Text, Slider} from './components'
const Inputs = {
Text,
Slider
};
export default Inputs;
export {default as Text} from './Text';
export {default as Slider} from './Slider';
export {default} from './Text';
src/components/Inputs/components/Text/index.tsx
export {default as Charts} from './Charts';
export {default as Inputs} from './Inputs';
import {Text, Slider} from './components'
const Inputs = {
Text,
Slider
};
export default Inputs;
export {default as Text} from './Text';
export {default as Slider} from './Slider';
export {default} from './Text';
这就是仅使用ES6导入/导出实现点表示法的方法