记录Vue3 TSX 基础信息

180 阅读2分钟

前言: 好记性不如烂笔头

pnpm sit:dev 18.18.0以上 components.ts export导出

在 Vue 3中,有两种声明组件的方式
常用的Template方式
TSX (TypeScript + JSX) ,tsx是一种声明组件的灵活方式,适合复杂逻辑场景中
优点:
  • 类型支持与代码提示:TSX 能够利用 TypeScript 的类型推断功能,减少开发中的类型错误。
  • 易于集成第三方库:TSX 更符合主流 JavaScript 库(例如 React)的写法。
  • TSX 允许更好地利用 JavaScript 的功能来创建可组合的组件。
  • 表达能力更加强,对于一些重复性的代码可抽取出来

PixPin_2025-07-21_13-48-21.png

PixPin_2025-07-21_13-47-52.png

缺点:
  • 对于不熟悉 TypeScript 或 JSX 的开发者来说,TSX 可能需要一定的学习时间。
  • 对于简单的模板,TSX 可能显得冗长且不如 Vue 的单文件组件(SFC)直观,尤其是在处理大量 HTML 时。
  • 虽然 Vue 3 支持 TSX,但 Vue 社区和生态系统的许多工具和库仍然主要围绕 SFC 开发,因此在使用 TSX 时可能会遇到一些兼容性问题。
基础用法:
安装依赖 npm install @vitejs/plugin-vue-jsx -D
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx'
export default { 
    plugins: [vue(), vueJsx()] 
}

支持v-model的写法,但是值需要用花括号包裹起来

<ElInput placeholder="请输入收货人姓名" v-model={formData.value.name} />

支持v-show 不支持v-if,大多数情况下需使用三元运算符判断展示

let flag = ref(false)
 
const caseFn = () => {  
    return (
        <div>
           <div v-show={flag.value}>显示</div>
           <div v-show={!flag.value}>隐藏</div>
        </div>
    )
}

const caseFn = () => {
    return (
        <div>
            {
                flag.value ? <div>显示</div> : <div>隐藏</div>
            }
        </div>
    )
}

在templete下使用v-for来循环页面,在jsx中需要使用list.map方法处理循环数据

注意点: 循环处理数据时如果是动态切换的需要return 出去,否则页面不显示

let arr = [1,2,3,4,5]
 
const caseFn = () => {
    return (
        <div>
            {
              arr.map(v=>{
                  return <div>{v}</div>
              })
            }
        </div>
    )
}

v-bind使用 {...item} ,这样可以将 props 对象中的所有属性绑定到 <div> 元素上。className={item.className} 绑定单个元素, 在子组件中使用props接受参数

let arr = [1,2,3,4,5]
 
const caseFn = () => {
    return (
        <div>
            {
                arr.map(item => { 
                    return (<li className={item} {...item}>{item}</li>) 
                })
            }
        </div>
    )
}
事件处理
  • 所有事件都为on开头,按react风格来
const caseFn = () => {
    return (
        <>
            <button onClick={ clickTap }>点击</button>
        </>
    )
}
 
const clickTap = () => {
    console.log('click');
}
样式
  • 没有内置的 <style> 支持,必须通过内联样式、CSS 模块或 CSS-in-JS 实现。
  • 没有像 SFC 那样的 scoped 样式支持,内联样式或 CSS 模块需要手动管理作用域。
  • 默认不支持直接在 TSX 中嵌入 <style> 标签。
import { defineComponent } from "vue"
import styles from "./styles.css"
export default defineComponent({ 
    setup() { 
        return () => ( 
            <div class={styles.container}>
                <span class={styles.text}>Hello, Vue 3 TSX!</span> 
            </div>)
    }
})
</style>
父子组件传值
父传子 onRefresh 接收子组件方法
<ShopOrder orderDetail={orderDetail.value} onRefresh={getData} />

子传父

props: {
    orderDetail: {
      type: Object as any
    }
 }

emits: {
  close: (value: Boolean) => value, //抛出子组件方法
}

setup(props, { emit }) {
  const goCloseDialog = () => {
     emit('close', false)
  }
}

插槽

定义子组件

import { defineComponent } from 'vue'

const Button = defineComponent({ 
    setup(props, { slots }) { 
        return () => <button>{slots.default ? slots.default() : ''}</button>
    }
}); 
    
export default Button

使用子组件

import { defineComponent } from 'vue'
import Button from './Button'

const App = defineComponent({ 
    setup() { 
        return () => ( <Button> <span>Click Me!</span> </Button> )
    }
})

export default App