您的位置:

了解tsx语法:最佳实践与技巧

一、对tsx语法的介绍

JSX是JavaScript语法的扩展,它允许我们在JavaScript中直接编写类似于XML的代码,用于描述用户界面和HTML元素。而TSX则是基于JSX的扩展,允许我们在TypeScript中编写JSX语法的代码。TSX可以让我们在编写React组件时,使用TypeScript的类型检查来避免一些常见的错误,在编译时就发现这些错误。

在TSX中,我们可以直接在TypeScript代码中编写类似于HTML的元素,比如div、p、button等,像下面这样:

function HelloWorld(props: {name: string}) {
  return 
  
Hello {props.name}!
; }

上面的代码中,我们定义了一个名为HelloWorld的函数组件,它接受一个props参数,其中包含一个名为name的字符串属性。在函数的返回值中,我们使用了一个div元素,其中包含了一个Hello和props.name的字符串插值表达式,最后返回这个div元素。

二、TSX的最佳实践

1. 使用接口声明组件的props

在定义React组件时,我们经常会使用props对象传递组件的属性,也就是一些配置信息和状态数据。为了避免在使用props时出现一些类型错误,我们可以使用接口来声明组件的props类型。像下面这样:

interface Props {
  name: string;
  age: number;
  onClick?: () => void;
}

function MyComponent(props: Props) { 
  return (
    
  
Name: {props.name}
Age: {props.age}
{props.onClick && }
); }

上面的代码中,我们定义了一个名为Props的接口,它包含了三个属性:name、age和一个可选的onClick回调函数。在MyComponent函数组件中,我们使用Props接口来声明了props的类型,然后在函数的返回值中使用了三个插值表达式来渲染props的值。

2. 使用枚举类型定义常量值

在编写React组件时,我们经常会定义一些常量值,比如组件的状态、类型、样式等等。为了避免在使用常量值时出现一些错误,我们可以使用枚举类型来定义常量值,并在使用时直接引用枚举项的名称。像下面这样:

enum Status {
  Draft = 'draft',
  Published = 'published',
  Archived = 'archived'
}

interface Props {
  status: Status;
}

function MyComponent(props: Props) {
  return 
  
Status: {props.status}
; } function App() { return ( <> ); }

上面的代码中,我们定义了一个名为Status的枚举类型,它包含了三个枚举项:Draft、Published和Archived。在MyComponent组件中,我们使用了Status枚举类型来声明了status属性的类型,并在函数的返回值中直接渲染了props.status的值。在App组件中,我们使用了MyComponent组件,并在props中传递了不同的Status枚举项。

3. 使用泛型类型定义函数组件

在编写React组件时,我们经常会定义一些通用的组件,比如列表、表单、对话框等等。为了使这些组件更加灵活和复用,我们可以使用泛型类型来定义函数组件,并在使用时传入不同的类型参数。像下面这样:

interface Item {
  id: string;
  name: string;
}

interface Props {
  items: T[];
  renderItem: (item: T) => React.ReactNode;
}

function List
   (props: Props
    ) {
  return (
    
     
    {props.items.map(item => (
  • {props.renderItem(item)}
  • ))}
); } function App() { const items: Item[] = [ {id: '1', name: 'Apple'}, {id: '2', name: 'Banana'}, {id: '3', name: 'Orange'} ]; return ( {item.name}} /> ); }

上面的代码中,我们定义了一个名为Item的接口,它包含了两个属性:id和name。在Props接口中,我们使用了泛型类型T来定义了items和renderItem属性的类型,并在List函数组件中使用了T来表示不同的类型参数。在函数的返回值中,我们通过map方法遍历items数组,并渲染了每一个item和相应的renderItem函数。在App组件中,我们定义了一个名为items的数组,并在props中传递了List组件和renderItem函数。

三、TSX的技巧

1. 使用Fragment代替外部div包裹

在编写React组件时,我们经常需要在JSX中使用多个组件或元素,但又不想用一个外部div元素包裹它们。为了解决这个问题,我们可以使用React提供的Fragment组件来包裹JSX中的多个元素。像下面这样:

function MyComponent() {
  return (
    <>
      

Title

Paragraph

); }

上面的代码中,我们使用了React提供的Fragment组件来包裹了h1和p元素,实现了多个元素的无父级元素包裹。

2. 使用TypeScript的类型别名

在编写React组件时,我们经常需要使用复杂的类型来描述组件的props属性,比如联合类型、交叉类型、可选属性等等。为了避免代码重复,在TypeScript中我们可以使用类型别名来定义这些复杂的类型,并在组件中重复使用。像下面这样:

type User = {
  id: string;
  name: string;
  age: number;
}

type Status = 'draft' | 'published' | 'archived';

type Props = {
  user: User;
  status?: Status;
}

function UserCard(props: Props) {
  return (
    
  

{props.user.name} ({props.user.age})

{props.user.id}

{props.status &&

Status: {props.status}

}
); }

上面的代码中,我们使用了类型别名来定义了User、Status和Props三个类型,分别表示用户对象、状态值和组件的props属性。在UserCard组件中,我们使用Props来声明了props属性的类型,并在函数的返回值中渲染了props属性的值。

3. 使用React.forwardRef传递ref

在编写React组件时,我们经常需要在组件内部使用ref来操作DOM元素或子组件。但是,有些时候我们需要将ref传递给组件的子组件,而传递ref的方式却并不那么简单。为了解决这个问题,React提供了forwardRef方法来传递ref。像下面这样:

interface Props {
  children: React.ReactNode;
}

const InnerComponent = React.forwardRef((props, ref) => (
  
   
{props.children}
)); function MyComponent() { const ref = useRef (null); useEffect(() => { if (ref.current) { console.log(ref.current.getBoundingClientRect()); } }, []); return (

Title

Paragraph

); }

上面的代码中,我们使用了React.forwardRef方法来创建了一个名为InnerComponent的函数组件,并在组件中定义了ref属性的类型。在MyComponent组件中,我们使用了useRef钩子来创建了一个类型为HTMLDivElement的ref,并在InnerComponent组件中传递了这个ref。在组件渲染后,我们使用useEffect钩子来操作ref.current属性,并输出了DOM元素的边界矩形信息。