2023 年终总结:vue-jsx 的最佳实践

前言

Hi,今天是大年29,在新年前的最后两天写一个年终总结,分享一下我是怎么加入 vue-macros 并走上开源的道路。

由于本人的工作中用到了ag-grid所以使用JSX定义cellRenderer成为了我的刚需。我挺喜欢JSX的书写方式,除了用三元表达式和map渲染列表,要是能和vue指令一样简单就好了,于是我在今年8月份左右的时候写了第一个库:

unplugin-jsx-vue-directive

在 JSX 中实现 v-ifv-for 指令,编译的时候把 v-if 转成三元表达式。最初的想法是让所有使用 JSX 的框架都可以使用,所以以把 JSX 放在库名的最前面。也因为这个库让我结识到了vue的大佬三咲智子

当我把这个库分享到了antfu的微信群里后,没过几秒钟智子就给我点了第一个 star,并邀请我把这个功能添加到 vue-macros 里。于是我开始研究 vue-macros,三天后提交了第一个PR

@vue-macros/jsx-directive

实现了v-if,v-for,v-slot,v-memo等常用的vue指令。

html 复制代码
<script setup lang="tsx"> 
import Child from './Child.vue'
const { foo, list } = defineProps<{ foo: number list: number[] }>() 
defineRender(( 
  <form onSubmit_prevent> 
    <div v-if={foo === 0}>
      <div v-if={foo === 0}>0-0</div>
      <div v-else-if={foo === 1}>0-1</div> 
      <div v-else>0-2</div> 
    </div> 
    
    <div v-for={(i, index) in list} v-memo={[foo === i]} key={index}>
      {i} 
    </div> 
    
    <Child v-on={{ submit: () => {} }}> 
      default slot 
      <template v-slot:bottom={{ bar }}> 
        <span>{bar}</span> 
      </template> 
    </Child> 
  </form> 
)) 
</script>

由于在JSX中的vue指令没有类型提示,所以又开发了 volar 插件@vue-macros/volar/jsx-directive。其实volar插件的原理和vite插件差不多,都是遍历ast语法树,只不过 volar 使用 TS 遍历,而 vite 使用 babel。找到 vue指令然后替换字符串就可以了,基本逻辑都可以复用。

@vue-macros/export-render

灵感来自于智子的 setup-sfc,原理很简单把 export default 转成 defineRender就可以了。

html 复制代码
<script setup lang="tsx"> 
// JSX passed directly 
export default <div>ok</div>

// Or using render function 
export default () => <div>ok</div> 
</script>

@vue-macros/short-bind

如果属性名和属性值一样,可以省略属性值。还可以配合 short-vmodel 一起使用。

html 复制代码
<template> 
<input :msg /> 
<!-- => <input :msg="msg" /> --> 
<demo $msg /> 
<!-- => <input $msg="msg" /> => <input v-model:msg="msg" /> -->
</template>

没想到在10月份的时候,智子告诉我尤雨溪同意把这个feature 加入到 vue3.4,然后我就给vue/core 提交了第一个 PR

vue-macros-cli

vue-macors init

vue-macros开发的命令行工具,根据你选择的vue-macros语法糖,自动配置tsconfig.jsonvite.config.ts或者nuxt.config.ts

vue-macors sg

得益于 ast-grep,你可以快速的把已有项目的vue template一键转换成vue jsx。之后我所有项目就开始用jsxvue了。

unplugin-vue-components-jsx

JSX中直接使用组件,和vue template一样不需要手动引入了。

灵感来自antfueslint-ts-patch,由于使用了module.register 去改写node_modules,所以需要node18以上版本。

transformer-attributify-jsx-sg

ast-grep 代替正则表达式实现unocssvalueless attributify。正则表达式真的不适合用来处理JSX这种复杂的表达式,虽然已经给unocss提了很多PR了,但新的问题还是不断出现。

相关提案: github.com/unocss/unoc....

volar-plugin-ignore-attributes

JSX中使用unocssAttributify Mode,会有类型提示的报错,官方的解决方案是把所有导致报错的属性注册到AllowedComponentProps里。

ts 复制代码
import type { AttributifyAttributes } from '@unocss/preset-attributify'

declare module '@vue/runtime-dom' {
  interface HTMLAttributes extends AttributifyAttributes {}
}

declare module '@vue/runtime-core' {
  interface AllowedComponentProps extends AttributifyAttributes {}
}

这样就会导致一个问题当我想看到组件有哪些属性的时候,这些属性也会跟着出现,影响调试。 所以我就写了这个volar插件去忽略这些报错的属性。

unplugin-vue-jsx-vapor

本来我是想做个JSX版的vapor,研究了一下vapor的源码后,既然vapor最后生成的也是dom,为什么我不先把JSX转成template再交给compiler-vapor去生成dom。还支持所有的vue指令

ts 复制代码
// vite.config.ts
import VueJsxVapor from 'unplugin-vue-jsx-vapor/vite'
import { compile } from '@vue/compiler-dom'
// or
// import { compile } from 'vue/vapor'

export default defineConfig({
  plugins: [
    VueJsxVapor({
      compile
    }),
  ],
})

由于vapor还未正式发布,你可以先用virtual-dom版的compiler来提前试用。还能获得和vue template一样的编译优化。

Playground: stackblitz.com/github/zhiy...

其他的库

还有一些试验性的库 太hack了就不一一介绍了 感兴趣的可以自己看看。

unplugin-jsx-short-bind

unplugin-vue-reactivity-function

相关推荐
麦麦大数据6 小时前
F032 材料科学文献知识图谱可视化分析系统(四种知识图谱可视化布局) | vue + flask + echarts + d3.js 实现
vue.js·flask·知识图谱·数据可视化·论文文献·1024程序员节·科研图谱
web打印社区7 小时前
使用React如何静默打印页面:完整的前端打印解决方案
前端·javascript·vue.js·react.js·pdf·1024程序员节
小光学长8 小时前
基于Vue的课程达成度分析系统t84pzgwk(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
前端·数据库·vue.js
麦麦大数据9 小时前
F033 vue+neo4j图书智能问答+知识图谱推荐系统 |知识图谱+neo4j+vue+flask+mysql实现代码
vue.js·flask·nlp·neo4j·智能问答·图书·1024程序员节
橙子1991101610 小时前
在 Kotlin 中,ViewModel 的获取
开发语言·vue.js·kotlin
疯狂的沙粒11 小时前
前端开发【工具函数】基于dayjs 封装的DateUtils工具函数,可以直接拿着使用
前端·javascript·vue.js·1024程序员节
海鸥两三14 小时前
Uni-App(Vue3 + TypeScript)项目结构详解 ------ 以 Lighting-UniApp 为例,提供源代码
vue.js·typescript·uni-app·1024程序员节
知识分享小能手14 小时前
uni-app 入门学习教程,从入门到精通,uni-app中uCharts组件学习((8)
vue.js·学习·ui·微信小程序·小程序·uni-app·echarts
布兰妮甜14 小时前
彻底清理:Vue项目中移除static文件夹的完整指南
vue.js·前端框架·static·1024程序员节