一、前置准备

完整用法请见文档:Vue 3 Babel JSX 插件

1. 安装插件

该文章是基于vite 构建的,所以安装的是 @vitejs/plugin-vue-jsx见文档

npm i @vitejs/plugin-vue-jsx

2. 配置vite.config.ts

// vite.config.ts
import vueJsx from '@vitejs/plugin-vue-jsx'

export default {
  plugins: [
    vueJsx({
      // options are passed on to @vue/babel-plugin-jsx
    }),
  ],
}

3. 配置tsconfig.json

{
  "compilerOptions": {
    "jsx": "preserve",
    "jsxFactory": "h",
    "jsxFragmentFactory": "Fragment",
    ...
  },
  ...
}

二、使用TSX

1. tsx的三种书写方法

1.1 直接返回一个渲染函数
export default function () {
  return (
    <>
      测试
    </>
  )
}
1.2 optionsAPI(不常用)
import { defineComponent } from 'vue'

export default defineComponent({
  data(vm) {
    return {
      num: 18
    }
  },
  render() {
    return (<>{this.num}</>)
  }
})
1.3 setup函数模式
import { defineComponent } from 'vue'

export default defineComponent({
  setup() {
    return () => (<>测试</>)
  }
})

2. tsx与template的区别(以下以setup函数模式为例)

2.1 {}

template 中 变量渲染使用{{}},而 tsx 使用 {},且可以直接使用 {} 代替 v-bind

2.2 ref的使用

templateref 会自动解包,而 tsx 不会,所以需要 .value

import { defineComponent, ref } from 'vue'

export default defineComponent({
  setup() {
    const num = ref(18)
  
    return () => (<>需要使用.value:{num.value}</>)
  }
})
2.3 v-show

tsx 支持 v-show

import { defineComponent, ref } from 'vue'

export default defineComponent({
  setup() {

    const flag = ref(true)

    return () => (<div v-show={flag.value}>v-show</div>)
  }
})
2.4 v-if

tsx 不支持 v-if 可以使用三元表达式代替

...
return () => (flag.value ? <div>flag为true</div> : <div>flag为false</div>)
2.4 v-for

tsx 不支持 v-for 可以使用map代替

...
const list = [{ name: '多多' }, { name: '小多' }, { name: '小凡' }]

return () => (
	list.map((item) => (<div>{item.name}</div>))
)
2.5 v-on

绑定事件按照React的风格来

  • 所有事件以 on 开头
  • 事件名称首字母大写
...
    const flag = ref(true)

    return () => (
      <>
        <button onClick={() => flag.value = !flag.value}>改变flag</button>
        <div>flag:{`${flag.value}`}</div>
      </>
    )

注意

  • 不带参数的函数不要加 ()onClick={fn}
  • 带参数的函数使用函数柯里化:onClick={()=>fn(e)}
2.6 Props
import { defineComponent, ref } from 'vue'

interface Props {
  name?: string
}

export default defineComponent({
  props: {
    name: String
  },
  setup(props: Props) {
    return () => (
      <>
        props: {props?.name}
      </>
    )
  }
})
2.7 emit
import { defineComponent, ref } from 'vue'

interface Props {
  name?: string
}

export default defineComponent({
  props: {
    name: String
  },
  emits: ['emit-test'],
  setup(props: Props, {emit}) {

    const fn = (num: number) => {
      emit('emit-test', num)
    }

    return () => (
      <>
        <button onClick={() => fn(11)}>派发</button>
      </>
    )
  }
})
2.8 插槽
import { defineComponent, ref } from 'vue'

export default defineComponent({
  setup() {

    const slot = {
      default: () => (<section>这是渲染的内容</section>),
      header: () => (<h2>这是标题</h2>)
    }
    
    return () => (
      <>
        <A v-slots={slot}></A>
      </>
    )
  }
})

const A = (_: any, { slots }: any) => (
  <>
    <div>{slots.header?.()}</div>  {/* 不设置默认值写法 */}
    <hr />
    <div>{slots.default ? slots.default() : '默认值'}</div> {/* 设置默认值 */}
  </>
)
2.9 v-model

tsx 支持 v-model

    const str = ref('')
    return () => (
      <>
        <input type="text" v-model={str.value} />
        {str.value}
      </>
    )
Logo

前往低代码交流专区

更多推荐