在vue3中使用更丝滑的去使用tsx
对于喜欢在vue3中使用tsx的小伙伴儿说,去书写属性的类型声明比去写实体的属性更为简单易用,但是在@vitejs/plugin-vue-jsx
中,并没有给我们提供这样的使用方式,之前我开发了一个tsx-auto-props插件从一定程度上解决了这个问题。但是这个插件还是没有完全满足我目前的需求,于是我又重新梳理了一下整个的需求,开发了一个新的插件vite-plugin-tsx-resolve-types。
这个插件解决了什么问题?
相比tsx-auto-props
而言,这个插件不仅仅局限于props
的类型声明,并且增加了emits
的类型声明的使用方式。所以这次插件可能所能解决的问题并不仅仅局限于tsx-auto-props
所能解决的问题。
下面我们通过几个简单的例子来带大家学习一下我们这款插件的用法。
安装
bash
pnpm add -D vite-plugin-tsx-resolve-types
使用
在vite.config.ts
中配置插件:
ts
import { defineConfig } from 'vite'
import tsxResolveTypes from 'vite-plugin-tsx-resolve-types'
import vueJsx from '@vitejs/plugin-vue-jsx'
export default defineConfig({
plugins: [
tsxResolveTypes(),
vueJsx(),
],
})
最基本的用法
你可以抛弃props
的属性定义,而直接采用props
类型定义的方式来实现属性的声明。
tsx
import {defineComponent} from "vue";
interface Props {
name: string
}
export const Test = defineComponent((props: Props) => {
return () => (
<div>{props.name}</div>
)
})
export const Test1 = defineComponent<Props>((props) => {
return () => (
<div>{props.name}</div>
)
})
export const Test2 = defineComponent({
setup(props:Props){
return ()=>{
return <div>{props.name}</div>
}
}
})
export const Test3 = defineComponent<Props>({
setup(props){
return ()=>{
return <div>{props.name}</div>
}
}
})
export default defineComponent<Props>((props) => {
return () => (
<div>{props.name}</div>
)
})
默认导出的setup
形式
tsx
import {defineComponent} from "vue";
interface Props {
name: string
}
export default defineComponent<Props>({
setup(props){
return ()=>{
return <div>{props.name}</div>
}
}
})
复杂类型用法
你可以使用一些比较复杂的类型来定义你的props
:
tsx
interface Props1 {
foo: string
}
interface Props2 {
bar: number
}
type Props = Props1 & Props2
export default defineComponent<Props>({
setup(props){
return ()=>{
return <div>{props.foo}{props.bar}</div>
}
}
})
interface Props4 extends Props1,Props2{
baz: boolean
}
export default defineComponent<Props4>({
setup(props){
return ()=>{
return <div>{props.foo}{props.bar}{props.baz}</div>
}
}
})
更多复杂用法的例子,大家可以自行探索。
默认值
在之前的tsx-auto-props
插件中,我们没有办法给props
设置默认值,但是在这个插件中,我们实现了给props
类型定义设置默认值的功能。
tsx
import { defineComponent } from "vue";
interface Props {
name: string
age?: number
}
export default defineComponent<Props>({
setup(props = {name: 'aibayanyu', age: 18}){
return ()=>{
return <div>{props.name}{props.age}</div>
}
}
})
const defaults:Props = {
name: 'aibayanyu',
age: 18
}
export const Test1 = defineComponent<Props>({
setup(props = defaults){
return ()=>{
return <div>{props.name}{props.age}</div>
}
}
})
export const Test2 = defineComponent({
setup(props:Props = {name: 'aibayanyu', age: 18}){
return ()=>{
return <div>{props.name}{props.age}</div>
}
}
})
emits类型转换
对于emits
的定义,我们也可以使用emits
类型定义的方式来实现。
tsx
import {defineComponent,SetupContext} from "vue";
interface Emits{
// 支持类似defineEmits的写法
click:[Event]
// 支持函数式的写法
change:(value:string) => void
}
const Test = defineComponent((props,ctx:SetupContext<Emits>)=>{
return ()=>{
return <div onClick={(e)=>ctx.emit('click',e)}>test</div>
}
})
// 支持行内写法
const Test12 = defineComponent((props,ctx:SetupContext<{click:[string]}>)=>{
return ()=>{
return <div onClick={(e)=>ctx.emit('click',e)}>test</div>
}
})
const Test1 = defineComponent({
setup(props,ctx:SetupContext<Emits>){
return ()=>{
return <div onClick={(e)=>ctx.emit('click',e)}>test</div>
}
}
})
const Test2 = defineComponent({
setup(props,{emit}:SetupContext<Emits>){
return ()=>{
return <div onClick={(e)=>emit('click',e)}>test</div>
}
}
})
这就是目前我们的插件所提供的能力,如果大家有什么更好的建议,欢迎大家来提交PR/issue,我们一起来完善这个插件。
如果您对我们的项目感兴趣的话,欢迎大家来给我们的项目点个star,您的支持是我们最大的动力。