# vue3中tsx语法避坑指南

vue3中使用tsx语法跟template写法会不一样,最基本像v-ifv-for要替换成js的语法。下面总结一下一些常见的不同,以便项目中遇到可以快速解决。

  1. 插槽的使用
// MyComponent.tsx 组件文件定义
setup(props, { slots }) {
  return () => <div>
    {slots.header?.()}
    {slots.default?.()}
  </div>
}
// MyComponent 组件调用
<MyComponent
  v-slots={{
    header: () => <div>header</div>,
    default: () => <div>body</div>,
  }}
/>

  1. Vue全局方法调用

(1)使用this调用出现tsx语法错误,如图: Vue全局方法调用 出现这种情况需要添加声明这个方法,如下:

declare module '@vue/runtime-core' {
  export interface ComponentCustomProperties {
    $toast: (msg: string) => void
  }
}

(2)setup方法中不能使用this,调用方式会不同:

const instance = getCurrentInstance()
instance?.proxy?.$toast('提示')
  1. v-model新用法

vue3定义v-model可以添加修饰符制定变量名称,如template语法中的v-model:show在tsx语法中不可这样写,需要替换成:

<van-popup v-model={[show, 'show']} />
  1. 事件绑定

tsx中事件绑定需要把@改成on,并且事件名称第一个字母改成大写。但是,在tsx组件中使用会出现语法提示未定义该属性,如图: 事件绑定 要解决该问题,需要在组件中声明props:

props: {
  onClick: Function as PropType<(event: Event) => void>
}

但是,在一些组件库中未做这个定义,我们不可能修改库中的声明,这个时候就要想办法绕过ts的检查。下面提供两种方式:

(1)通过别名声明组件

export default defineComponent({
  components: {
    'van-button': Button
  },
  setup () {
    const handleClick = () => {}
    return () => <van-button onClick={handleClick}></van-button>
  }
})

(2)通过解构定义属性

return () => <Button type="primary" {...{onClick: handleClick}}></Button>

这种方式优点是,组件内定义了什么属性,在vscode里面有比较好的提示。 缺点也有,一是需要在之前已经定义了有效属性,如上面案例的type="primary";二是属性语法定义跟传统不一致。