vue3+tsx开发语法详解

226 阅读7分钟

很多组件库都使用了TSX的方式开发,主要因为其灵活性比较高,TSXSFC开发的优缺点就不介绍了,这里主要说一下将SFC项目改造为TSX的过程。

安装JSX库

faedab64034f78f0b0cba4c5cf94e45fb2191c77.webp

安装完之后在vite.config.ts进行插件使用,代码如下:

95eef01f3a292df52285b6930494b26a35a87326.webp

然后就可以愉快的使用TSX来开发Vue组件了,下面主要说一下SFCTSX的部分区别。

基本语法对照 SFC

defineComponent 和 setup

SFC方式结构固定:template、script、style

0823dd54564e92583b09a07125273f52cdbf4ea4.webp

TSX方式就完全是一个ts文件的写法,没有模板template和样式style

9825bc315c6034a88dd8926e77b6a75e08237653.webp

setup中函数的返回值有多种方式,可以直接返回html,这个适合结构简单的页面,如果返回比较多,可以使用如下方式:

241f95cad1c8a7865d780621d8ac273771cf50fb.webp

如果是多节点,可以使用空符号包裹

8435e5dde71190efb239bb2772be731cfffa60bc.webp

在以上的方式中我们把除了布局以外的逻辑都写在//Todo部分,但是有时候我们需要做一些按条件渲染的逻辑,那么也可以在return里加处理逻辑,例如:

18d8bc3eb13533fa905a792d7876131540345b71.webp

这种方式类似v-if,但是和v-if还是有点区别,v-if可以作用在更小的范围,而这种方式只适合整个组件的条件渲染,这个可能不好理解,在下面v-if的使用中我们会看到区别。

v-if

使用条件判断语句来实现v-if的功能,一般是三目运算符

359b033b5bb5c9ea1a88924d639c580a3bf3b351.webp

在这里你可以看到v-if的使用和我们上面的条件返回不一样,区别就是整体渲染没有大的变化,只是其中部分地方要按条件显示。

v-bind

绑定变量,也就是简写的:冒号,修改方式就是将冒号去掉,把双引号改为大括号

a71ea8d3fd1f41343015591d93ba7bc0d0c85ee7.webp

v-for

采用map循环的方式,返回一个数组

dbb44aed2e738bd49628c0b3162e69dc267ff953.webp

自定义指令

自定义指令和普通指令v-model一样

3ac79f3df8dcd1000330a86dc52ea91ab8122f7a.webp

插槽

插槽有两种实现方式,一种是用v-slots绑定对象,一种是直接在元素中使用对象。

63d9f2d3572c11df99d3de2bd5828cdaf603c2ec.webp

c995d143ad4bd113c66209cae50a4a0549fb05cf.webp

props

父组件向子组件传值

6159252dd42a2834a8d017f7ee1027e014cebf0c.webp

需要注意的是,prop传递过来的值如果没有默认值,需要判断是否为空,可以使用计算属性或者条件渲染处理。

emit

子组件向父组件传值

3ac79f3df8dcd100b93cd628c52ea91ab8122f42.webp

事件监听

事件监听就是v-on或者@,在TSX中事件以on开头,即使我们的自定义事件没有on,也要在监听的时候加上,一般都采用的是小驼峰的方式。

7aec54e736d12f2e9c1d2cc9f7673b68843568ab.webp

自定义事件只需要在事件名前面加上on即可,参数传递与上面一致

f31fbe096b63f62464aa82053be105f21b4ca375.webp

TSX中处理事件不能使用事件修饰符,因此需要在事件函数中自行处理,例如冒泡、阻止默认行为等。

属性/事件继承

对于这个我也不知道怎么描述,当我们给一个组件传递属性和事件时,一般子组件在props中接收属性值,emits中接收事件,但是我们也可以传一些额外的属性和事件,即不在propsemits中的属性和事件,虽然这是不推荐的做法,但是有时候当我们封装第三方库的时候,这种用法就非常的方便。具体看如下代码:

d1a20cf431adcbef4e77c469120ac0d7a2cc9f4a.webp

SFC中,在template中我们可以通过$attrs获取到额外的属性和方法,script中可以通过getCurrentInstance方法获取组件对象,然后通过.attrs拿到属性和方法。

TSX中,直接通过attrs获取属性和方法,通过{...attrs}把属性和方法传递给子元素。

其他命令

v-showv-modelSFC中使用一样,这里不做示例

组件引用

通过ref获取组件dom信息

9358d109b3de9c82c091223dd6246e0018d84338.webp

对外暴露属性和方法

在父组件中直接调用子组件的属性和方法

7aec54e736d12f2e0836b5e2fa673b68843568b5.webp

样式修改

样式的改造一度是我切换TSX的最大痛点,因为在SFC中最麻烦的是修改第三方库的样式,一般要用到:deep,而且有时候还不一定成功,非常麻烦,改为TSX后我一直不知道怎么解决这种问题,后来搞定以后再回过头来看,发现是vue写久了养成了固定思维。我们在vue文件中写的样式都包含在scoped下面,如果不加scoped就可能会造成全局样式污染。那为什么会造成全局样式污染?又为什么加了scoped就不会呢?实际上我们只要知道CSS基础,明白CSS中的样式优先级即可。vue生成的项目最终还是会回归到htmlcssjs来,因此我们从这里来理解就方便多了。

  • 为什么会造成全局样式污染?

这个不是vue的专利,而是css本身的优先级问题,就是如果我们定义了相同的css类,并以相同的方式来使用它,那么根据先后加载顺序,就会导致后加载的覆盖掉先加载的样式,造成先加载的样式无效,这就是所谓的样式污染。

  • 为什么加了scoped就不会造成样式污染呢?

我们看一个简单的例子:

562c11dfa9ec8a13b6bed33c41a67f85a2ecc0f3.webp

看一下html和css源码

a044ad345982b2b78ae47d4a870825e577099b71.webp

可以看到,vue组件在渲染的时候,会给元素增加一个属性data-v-xxxx,然后在生成样式的时候也会在样式上加上[data-v-xxxxx],这是css属性选择器的用法,这样根据css选择器的优先级,这个属性就具有唯一性。

但是在TSX中没有了scoped怎么办?很简单,回归原始的css即可。在原始css中需要我们自己来保证css选择的唯一性,具体做法就是给组件内使用的css类都加上唯一前缀,例如组件名称为Child,那么所有的css类都加上child-xxx,因为我们肯定要保证组件名称的唯一性,所以这样下来对应的样式也就是唯一的。这就要求我们给所有需要修改样式的元素都加上类或者自定义属性,以便于我们可以通过唯一的css选择器选中它。

示例如下:

创建一个css文件:child.css

b219ebc4b74543a90fb201cbabb26488b80114b8.webp

在tsx文件中引用

fc1f4134970a304e1b0d58d76c6d498cc9175c24.webp

除了上面这种保证样式名称唯一的方式以外,vue其实一直为我们提供了另外一种方式-css module,具体来讲就是把css作为模块引入到js中,然后会生成一个唯一的名称,在以前用webpack的时候还需要装额外的包,现在vite已经帮我们集成了,只需要在vite.config.ts中加一下配置即可。

a8014c086e061d950aa47912cc51e4db63d9ca6e.webp

这里规定css类名的命名规则为小驼峰,即child-item类在js中会变成childItem变量。但是要实现css module的功能,对css文件命名由要求,必须在后缀名前面是module,例如xxx.module.cssxxx.module.lessxxx.module.scss

示例如下:

创建一个css文件:child.module.css

b03533fa828ba61e0e3e9a13f7917900314e596e.webp

在tsx文件中引用

4bed2e738bd4b31cdbfb59ba5773c9759f2ff819.webp

打开浏览器看一下源码

6d81800a19d8bc3ee49d9c9d392e4814a9d34504.webp

可以看到元素上绑定的css和全局的css都出现了变化,这种方式我们就不需要去关注编写的css是否是唯一的,vite会帮我们自行处理,只是在使用的时候有一些区别。

除了常规的css使用,我们还有动态class的使用。

aec379310a55b3196ef56684f40c6c2ccefc1767.webp

我们把需要的class处理成一个数组给它即可。

除了动态class还有动态style的使用。

0824ab18972bd407486658c6c32c705b0eb3099c.webp

总结

目前对于大部分场景的使用都写到了,如果后期有其他的语法糖在进行补充,示例项目:vue3-tsx-todo,请在gitee上进行找

0df3d7ca7bcb0a461dda0e28ddc6182e6a60af5c.webp

转载:baijiahao.baidu.com/s?id=174357…