

使用 JSX/TSX 开发 Vue3 组件
source link: https://zhuanlan.zhihu.com/p/153387704
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

使用 JSX/TSX 开发 Vue3 组件
写完下面这篇文章之后
就想着要不就着手开发一个完全为 Vue3 设计的 JSX 插件吧,于是就有了:
https://github.com/HcySunYang/vue-next-jsxgithub.com这个插件已经是可使用的状态了,我正在使用该插件在另外一个项目中,说说这个插件的设计原则和基本用法
直接使用 TSX
Vue3 的确可以直接使用 tsx
开发,唯一需要处理的就是 children
,而且处理起来还是比较不爽的,例如你不能这么写:
<div>
<p>1</p>
<p>1</p>
</div>
<div>
{
[
<p>1</p>,
<p>1</p>
]
}
</div>
这还是挺恶心的,不过也不是没有办法,可以封装一个工具函数:
function JSXFactory(tag: any, props: any, ...children: any) {
if (
typeof tag !== 'string' &&
typeof tag !== 'symbol' &&
!tag.__isTeleport &&
!tag.__isKeepAlive
) {
// Component
children = children[0]
}
return createVNode(tag, props, children)
}
然后在 tsconfig.json 中配置 jsxFactory
为我们封装的这个函数就可以了。但是这个函数限制了我们在为组件传递 slots
时只能:
const App = {
setup() {
const slots = {
foo: () => <p>foo</p>,
bar: () => <p>bar</p>,
}
return () => <Hello>{ slots }</Hello>
}
}
但是这也没啥问题嘛。
有了 JSXFactory
工具函数之后其实我们可以很开心的用 tsx
写了,那为啥还要 jsx
插件呢?这是因为使用了 jsx
语法后我们丢失了很多模板中提供的便利能力,例如事件修饰符、v-model
之类的, 因此 jsx
插件还是有必要的,但是不是必须的。
下面说说 https://github.com/HcySunYang/vue-next-jsx 的设计原则和功能。
既支持 JSX 又支持 TSX
tsx
中不支持 amespaced attribute
,详见:https://github.com/microsoft/TypeScript/issues/7411 ,但 babel 中是支持,这就意味着你在 jsx 中可以这么写:
<p v-on:click={ handler } ></p>
但是 tsx
中则不行,为了语法统一,我决定不允许在属性名中使用 :
,而是使用 -
替代 :
<p v-on-click={ handler } ></p>
统一语法的好处是:降低不同项目差异带来的额外负担/困扰(有的人使用 : 有的人使用 -)。
无论是 jsx 还是 tsx,修饰符都不允许使用 .
,而是使用 _
代替:
<p v-on-click_stop={ handler } ></p>
对于事件,vue-next-jsx
支持全部的模板中可用语法,例如:
<div v-on-click_middle={ handler }></div>
<div v-on-click_stop={ handler }></div>
<div v-on-click_right={ handler }></div>
<div v-on-keyup_esc={ handler }></div>
<div v-on={ obj }></div>
v-model
Vue2 中的 .sync
被 v-model:foo
代替了,例如:
<!-- Vue2 -->
<Comp :foo.sync="val" />
<!-- Vue3 -->
<Comp v-model:foo="val" />
在 jsx 中,把 :
换成 -
:
<Comp v-model-foo={ refVal.value }/>
也可以带修饰符,用 _
分割:
<Comp v-model-foo_a_b={ refVal.value }/>
v-bind
在 j/tsx
中不需要 v-bind
,直接使用 jsxExpressionContainer
和 jsxSpreadAttribute
代替:
<Comp foo={ refVal.value } { ...props } bar="bar" />
slots
我不准备支持 v-slot
,这是因为它会导致类型丢失,例如:
<Comp>
<template v-slot-foo="props">
</template>
</Comp>
这里的 props
没有类型,它就是一个字符串,而且我始终推荐像如下这样为组件传递插槽:
<Comp>{ mySlots }</Comp>
至于插槽 mySlots
我们可以自行构建它:
const mySlots = {
default: () => [<p>默认插槽</p>]
}
KeepAlive 和 Teleport
这两个组件比较特殊,他们的子节点不会作为 slots 存在,而是当做正常的 children,不过你不用担心,vue-next-jsx 帮你处理了。
Optimization mode
优化模式,正如 https://zhuanlan.zhihu.com/p/150732926 这篇文章中讲述的,我们可以在 jsx 插件中利用这些信息,尽可能的提升性能。
在 babel.config.json
中打开优化模式:
{
"presets": [
"@babel/env"
],
"plugins": [
["@hcysunyang/vue-next-jsx", {
// 开启优化模式
"optimizate": true
}]
]
}
实际上,你可以查看 vue-next-jsx
的测试用例生成的 ,并与 Vue3 Compiler
对比,他们的行为是一致的,包括及其复杂的情况。
指定 source
source
指的是 ImportDeclaration
语句的 source
,例如:
import { createApp } from 'vue'
这里的 source
就是 vue
,但是你可能安装的不是 vue
而是 @vue/runtime-dom
,这时你需要指定 source
:
{
"presets": [
"@babel/env"
],
"plugins": [
["@hcysunyang/vue-next-jsx", {
// 指定 source
"source": "@vue/runtime-dom"
}]
]
}
v-html / v-text
在 jsx
中支持这两个指令意义不大,全当顺手,它们的使用与在模板中相同:
<p v-html={ refHtml.value }></p>
<p v-text={ refText.value }></p>
Recommend
-
22
使用 tsx + vue3陶文problem solvervue3 的组件能不能在 tsx 中带类型提示的使用,就...
-
12
New Bitcoin Fund Starts Trading on TSX – TrustnodesThe Toronto Stock Exchange (TMX/TSX) has listed the CI Galaxy Bitcoin Fund by CI Global Asset Management and Galaxy Digital Capital Management. The fund has just began trading yeste...
-
12
在 vue 中使用 jsx 与 class component 的各种姿势发表于2019-09-17更新于2020-03-12字数统计992阅读时长8分 在之前我们分享过一次 ...
-
9
⚠️ Vue 3 TSX本篇基于 Vue 3.0.7, vite 2.1.2 编写,由于 Vue 与 vite 改动较大,以最新版本为准,本文仅供参考。写本篇文章主要是为了记录在正式使用 Vue 3 + vite 2 投入开发中遇到的一些问题,不适合没有任何 Vue 开...
-
6
-
2
V2EX › 程序员 求一个针对 React+TSX 的 ESLint+Prettier 的 Boilerplate xlsepip...
-
6
tile_source.tsx · GitHub Instantly share code, notes, and snippets.
-
5
组件不能作为JSX组件使用,出现该错误有多个原因:null 返回单个JSX元素下面是一个错误如何发生的示例。// App.tsx // :no_entry:️ 'App' cannot be used as a JSX component. // Its return type 'Element...
-
5
V2EX › Vue.js vue3 jsx 和 template 哪个性能好
-
13
大家好,我是蔓越莓曲奇,今天我想给大家分享的是我最近开源的中后台管理系统模板,Vue TSX Admin 。 正如项目名称所表述的,该项目是完全通过 Vue3 + TSX 开发的。 为什么使用 JSX 写中后台管理 在讲为什么使用 JSX 前,我想先说些在中后台业务开发...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK