TSX、JSX语法应用vue3
点击关注公众号,“技术干货”及时达!
前言JSX语法让程序员体验到前所未有的舒爽,在vue3中使用jsx,既能够让我们体会到javascript的灵活,又能使用vue响应式所带来的便捷。而在Vue3中,快速过渡到TSX也是轻而易举的。
工程搭建通过执行npm init vue来创建一个Vue工程。
工程地址你可以在以下地址找到本文使用的工程示例:https://gitee.com/z-shichao/vue_tsx
组件定义:defineComponent在Vue3中,defineComponent是一个用于定义组件的函数API。它的作用主要有三个方面:
创建组件选项对象:defineComponent允许你定义一个包含组件配置信息的选项对象,如组件的属性、方法、生命周期钩子等。类型推断支持:使用defineComponent可以帮助TypeScript更好地推断组件的类型,从而提高开发效率和代码的健壮性。提供组件定义上下文:defineComponent内部对组件选项对象进行一些处理,包括生命周期钩子的转换、模板的编译等,从而提供了一个统一的组件定义上下文,使得组件的定义更加清晰和一致。这里有个专门讲解defineComponent的文章 :https://juejin.cn/post/6994617648596123679
tsx语法tsx有种书写模式:函数语法,选项语法
//选项式
import{defineComponent}from"vue"
exportdefaultdefineComponent({
setup(){
return()=(divvue3+tsx/div)
}
})
//函数式
exportdefaultdefineComponent(()={
return()=(divvue3+tsx/div)
})
使用选项语法还是函数语法主要取决于个人习惯。下文示例将使用选项式进行讲解。
「注意」:返回的是一个函数,在函数中返回的是一个JSX元素。JSX元素中必须有一个根标签。如果不想使用根标签,可以使用代替,该标签不会在页面中渲染。
插值语法exportdefaultdefineComponent({
setup(){
lettext=refstring('我是文本内容')
return()=(div{text.value}/div)
}
})
「注意」:使用ref定义响应式数据时,在模板中需要使用.value来访问。
事件绑定exportdefaultdefineComponent({
setup(){
lettext='我是文本内容'
return()=(
div{text}/div
buttononClick={()={alert('您点击了我')}}点我/button
)
}
})
事件修饰符后边加驼峰事件修饰符
exportdefaultdefineComponent({
setup(){
lettext='我是文本内容'
return()=(
div{text}/div
buttononClickStop={()={alert('您点击了我')}}点我/button
)
}
})
「注意」:使用大括号{}进行插值,使用on+事件名(小驼峰命名法)进行事件绑定,自定义事件也是一样的。
jsx中移除了部分指令:v-bin、v-for、v-ifv-bind:使用大括号{}进行包裹
exportdefaultdefineComponent({
setup(){
lettext='我是文本内容'
letstyle={
background:'red'
}
return()=(
divstyle={style}{text}/div
buttononClick={()={alert('您点击了我')}}点我/button
)
}
})
v-for:使用数组方法mapexportdefaultdefineComponent({
setup(){
letitems=['张三','李四','王五']
return()=(
{items.map((item)=div{item}/div)}
)
}
})
v-if:使用三元表达式
exportdefaultdefineComponent({
setup(){
letisShow=refboolean(true)
return()=(
div{isShow.value?div我出来饿了/div:''}/div
buttononClick={()={isShow.value=!isShow.value}}点我/button
)
}
})
注意:js要写在{}里面,返回值是是一个可渲染的元素或元素组成的数组。
插槽默认插槽import{defineComponent,ref}from"vue"
exportdefaultdefineComponent({
setup(props,{slots}){
lettext=refstring('我是默认插槽')
return()=(Child{text.value}/Child)
}
})
letChild=(props:any,{slots}:any)={
returndiv{slots.default()}/div
}
具名插槽import{defineComponent,ref}from"vue"
exportdefaultdefineComponent({
setup(props,{slots}){
lettext=refstring('我是默认插槽')
return()=(Child
{{
default:()=text.value,
name1:()='我是插槽1',
name2:()='我是插槽2'
}}
/Child)
}
})
letChild=(props:any,{slots}:any)={
returndiv
div{slots.default()}/div
div{slots.name1()}/div
div{slots.name2()}/div
/div
}
作用域插槽exportdefaultdefineComponent({
setup(props,{slots}){
lettext=refstring('我是默认插槽')
return()=(Child
{{
default:()=text.value,
name1:()='我是插槽1',
name2:(parms:string)=div
{parms}
/div
}}
/Child)
}
})
letChild=(props:any,{slots}:any)={
letparms:string='我是参数'
returndiv
div{slots.default()}/div
div{slots.name1()}/div
div{slots.name2(parms)}/div
/div
}
还可以通过props传参向子组件传递元素
import{defineComponent,ref}from"vue"
exportdefaultdefineComponent({
setup(props,{slots}){
lettext=refstring('我是默认插槽')
return()=(Child
childs={[
div我是一/div,
div我是二/div
]}/Child)
}
})
letChild=(props:any,{slots}:any)={
returndiv
div{props?.childs[0]}/div
div{props?.childs[1]}/div
/div
}
使用css scoped在Vue 3 中,如果想要在 TSX 文件中使用 CSS scoped 样式,通常不能直接在 TSX 文件中实现 scoped 样式。你可以在 .vue 单文件组件中的 script 标签中编写 TSX 代码,并且将 script 标签的 lang 属性设置为 'tsx',然后在 style 标签中添加 scoped 属性来实现 scoped 样式。
scriptlang="tsx"
import{defineComponent}from"vue"
exportdefaultdefineComponent({
setup(){
return()=(
divclass='text'cssscoped/div
)
}
})
/script
stylescoped
.text{
background:
}
/style
vue3+tsx中定义props:import{defineComponent,PropType}from"vue"
exportdefaultdefineComponent({
setup(){
return()=(
div我是父组件/div
Textname={'我是传进来的name'}/
)
}
})
//子组件
constText=defineComponent({
props:{
name:{
type:StringasPropTypestring,
required:true
}
},
setup(props){
return()=(
div{props.name}/div
)
}
})
import{defineComponent,PropType}from"vue"
exportdefaultdefineComponent({
setup(){
return()=(
Textname='我是传进来的name'/
)
}
})
注意:在tsx中定义类型时,只能定义比较笼统的Object、String等,这种类型为什么比较笼统呢,因为在js语言中Object在任何变量的原型上都存在,当你定义一个Object时他就会和any类型时类似的,其他类型同理,当我们想要定义某个类型时,我们只能使用as+ PropType的形式。
简化props的使用:首先要了解定义string会报错呢,因为我们使用了defineComponent帮我们进行了类型推断定义。那我们可不可以不使用,自己使用ts来规范我们的类型呢。当然可以!!!
方案一:不适用defineComponent 自己使用ts来进行类型定义。
可以看到使用ts也可以进行类型定义,并且更为简便。当然参数在子组件里也是可以定义接收的。缺点就是jsx中是不能使用这种方式的。
import{defineComponent}from"vue"
exportdefaultdefineComponent({
setup(){
return()=(
div我是父组件/div
Textname='张三'/
)
}
})
interfaceProps{
name:string,
age?:number
}
constText=(props:Props,ctx:any)={
returndiv{props.name}/div
}
方案二:混编
https://juejin.cn/post/7143053446365577253?searchId=202404031524149C416A3419D9B87C6B19
方案三:使用# Vue Macros构建项目
https://vue-macros.dev/zh-CN/guide/getting-started.html
vue中jsx语法和模板语法的优缺点:「JSX语法:」
优点:
「更灵活的语法:」 JSX允许在模板中使用JavaScript表达式,使得模板更加灵活和表达能力更强,更容易阅读和理解JSX的代码。「组件逻辑更直观,易维护:」 JSX让组件的结构和逻辑更加紧密,因为你可以在组件中直接编写JavaScript逻辑,并且在同一个文件中可以写多个组件,将相关性较强的组件放在一起更易维护。「性能较好:」使用JSX编写Vue 3组件会比使用模板语法的组件具有更好的性能。因为JSX可以直接将组件转换为纯JavaScript 代码,而模板语法需要在运行时进行解析和编译。缺点:
「学习曲线较陡:」 对于新手来说,学习JSX语法可能需要一定的时间,特别是对于那些不熟悉React或其他使用JSX的框架的人来说。「与HTML混合:」 有些开发者可能觉得在JavaScript中嵌入HTML的方式不够直观,因为它打破了HTML和JavaScript的分离原则。「与模板的差异」:TSX(或 JSX)语法与 Vue 的模板语法有一定的差异,可能需要一定的适应时间,并且不支持一些模板特有的语法和指令。「模板语法:」
优点:
「易于学习和上手:」 模板语法更接近传统的HTML,因此对于初学者来说更容易理解和上手。「HTML代码直观:」 模板语法使得HTML代码更加直观,可以更清晰地看到组件的结构。「编辑器支持良好:」 大多数编辑器对Vue模板语法有良好的支持,提供语法高亮、自动补全等功能。缺点:
「表达能力受限:」 模板语法相比于JSX在表达能力上受到一定的限制,因为因为它不能像JSX那样直接在模板中使用JavaScript表达式。「组件与逻辑分离:」 使用模板语法时,组件的结构和逻辑可能会分离得较为明显,因为一些逻辑需要放在JavaScript中,而不是直接嵌入模板中。总的来说,选择JSX还是模板语法取决于个人的偏好、团队的技术栈以及项目的需求。在Vue 3中,JSX语法的支持更加完善,因此如果你对JavaScript更为熟悉,或者项目需要更高的灵活性和表达能力,那么可以考虑使用JSX语法。而对于简单的项目或团队中大多数成员都熟悉HTML的情况下,模板语法可能更为适合。
点击关注公众号,“技术干货”及时达!
阅读原文
网站开发网络凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设、网站改版、域名注册、主机空间、手机网站建设、网站备案等方面的需求...
请立即点击咨询我们或拨打咨询热线:13245491521 13245491521 ,我们会详细为你一一解答你心中的疑难。 项目经理在线