vue官方推荐的是单文件 .vue 编写组件,简单易学但没有jsx灵活性,很多知名的UI库最终选择了使用jsx,例如:ant-desing-vue, vant。但是在 vue 中使用 jsx 也存在一些问题。比如:大部分 vue 指令无法使用或者很难使用。在 vue3 中专门开了个 issue 讨论解决方案,至今没有优雅的解决方案。 jsv 而不是 jsx 可能是更好的解决方案。

一、先看看 .vue 与 .jsx 的比较

1. 变量作用域比较

  • 1.1 .vue 中无法使用当前作用域变量,必须return后才能使用
// Scope.vue
<template><div>{{ state.count }}</div><button @click="handleClick">点击加1</button>
</template><script>
import { reactive } from "vue";
export default {setup() {let state = reactive({ count: 0 });function handleClick() {state.count++;}return { state, handleClick };},
};
</script>
  • 1.2 .jsx 中可以直接使用当前作用域的变量
// Scope.jsx
import { reactive } from "vue";export default {setup() {let state = reactive({ count: 0 });function handleClick() {state.count++;}return ()=>(<div><div >{ state.count }</div><button onClick={handleClick}>点击加1</button></div>)},
};

2. 灵活性比较

  • 2.1 .vue 中一个文件只能写一个组件
// NoMulti.vue
<template><Title :title="state.title" />
</template><script>
import { reactive } from "vue";
import Title from "./Title.vue";
export default {components: { Title },setup() {let state = reactive({ title: "jsv-compiler" });return { state };},
};
</script>
// Title.vue
<template><h1>hello {{title}}</h1>
</template><script>
export default {props: {title: String}
}
</script>
  • 2.2. .jsx 中可以写多个组件
// Multi.jsx
import { reactive } from "vue";export default {setup() {let state = reactive({ title: 'jsv-compiler'});let Title = ()=><h1>hello {state.title}</h1>return ()=>(<div><Title /></div>)},
};

3. 指令比较

  • 3.1. .vue 原生支持优雅的指令写法
<A v-model:argument.modifer="val" />
  • 3.2. .jsx 本身不支持指令
    社区有多种指令的书写方式,各种千奇百怪,为此还开了issue讨论,至今仍然没有友好的解决方式。因此可以暂时认为 .jsx 不支持指令或支持的不好. https://github.com/vuejs/jsx/issues/141
<A v-model={[val, 'argument', ['modifier']]} />

4. 运行时性能比较

  • 4.1. .vue 支持hoist,block,patchProps等运行时性能提升,至少比 .jsx 性能快了3倍
    https://vue-next-template-explorer.netlify.app
// 编译前
<div><div>静态节点</div><div >{{state.count }}</div>
</div>
// 编译后
const { createVNode: _createVNode, toDisplayString: _toDisplayString, openBlock: _openBlock, createBlock: _createBlock } = Vueconst _hoisted_1 = /*#__PURE__*/_createVNode("div", null, "静态节点", -1 /* HOISTED */)return function render(_ctx, _cache, $props, $setup, $data, $options) {return (_openBlock(), _createBlock("div", null, [_hoisted_1,_createVNode("div", null, _toDisplayString(_ctx.state.count), 1 /* TEXT */)]))
}
// Check the console for the AST
  • 4.2. .jsx 没有运行时优化
    https://www.babeljs.cn/repl
// 编译前
<div><div >static node</div>  <div >{ state.count }</div>
</div>
// 编译后 (使用 vite 工具编译)
jsx("div",null /* @__PURE__ */,jsx("div", null, "static node") /* @__PURE__ */,jsx("div", null, state.count)
)

5. 生态比较

  • 5.1. 当前知名的UI库比如 ant-desing-vue,vant 内部采用了 jsx
  • 5.2. 但对外提供的组件仍然是 vue的模板语法。对于使用者如果要用 jsx,还得自己把 vue 改成 jsx,代价高昂呀!

二、这才是正文:是 jsv 不是 jsx !

那有没有一种解决方案,既有 jsx 的灵活性,又有原生支持vue指令和运行时高性能,在 .js 中直接使用 vue 模板语法?就像这样

import { reactive } from "vue";export default {name: "App",setup() {let state = reactive({ title: 'jsv-compiler',count: 0 });function handleClick() {state.count++;}let Title = <template><h1>hello {{state.title}}</h1></template>return (<template><Title /><div>{{ state.count }}</div><button v-on:Click="handleClick">点击加1</button></template>)},
};

目标有了那就开始魔改吧。我写了个编译器集成了vite插件实现:jsv-compiler

1. 创建vue3项目

npx create-vite-app <your projectname>

2. 安装依赖包

npm i -D jsv-compiler

3. 配置插件

文件: vite.config.js

import {jsvPlugin} from 'jsv-compiler'export default {configureServer: [jsvPlugin]
}

4. 使用示例

// App.js
import { reactive } from "vue";export default {name: "App",setup() {let state = reactive({ title: 'jsv-compiler',count: 0 });function handleClick() {state.count++;}let Title = `<template><h1>hello {{state.title}}</h1></template>`return (`<template><Title /><div>{{ state.count }}</div><button v-on:Click="handleClick">点击加1</button></template>`)},
};

5. 语法高亮

在vscode的插件市场中下载插件: jsv
因为是第一个版本,所以需要在 <template></template> 旁边加上反引号 才能在vscode中实现语法高亮,实际在编译层面是不需要加反引号的。

6. 编译结果

还是用上面那个例子

// 编译前
<div><div>静态节点</div><div >{{state.count }}</div>
</div>
// 编译后
(() => {const _hoisted_1 = /*#__PURE__*/_createVNode("div", null, "静态节点", -1 /* HOISTED */)return function render(_ctx, _cache) {return (_openBlock(), _createBlock("div", null, [_hoisted_1,_createVNode("div", null, _toDisplayString((() => {try {return state} catch {return _ctx.state}})().count), 1 /* TEXT */)]))}
})()
  1. 为了保留 hoisted 特性,编译后的结果是一个自执行函数,返回渲染函数。利用闭包特性,仍然可以取到_hoisted_1;
  2. 为了使用当前作用域的变量 state , 我将_ctx.state编译成自执行函数:
(() => {try {return state} catch {return _ctx.state}
})()

三、总结

在 .js 中使用 vue 模板语法 (简称 jsv

vue3 模板 jsv jsx
灵活性 不灵活 灵活 灵活
文件中组件数量 1个文件1个组件 1个文件多个组件 1个文件多个组件
能否使用当前作用域变量 不能,需在setup()方法中return后才能使用 可以使用 可以使用
是否很好支持指令 原生支持 原生支持 不支持或支持不友好
运行时性能 支持hoist,createBlock,patchProps 支持hoist,createBlock,patchProps 不支持
自动热更新 支持 不支持 不支持

值得一提的是 jsv 保持了原本 vue 的高性能,支持hoist,createBlock,patchProps等在 jsx 中难以实现的特性,比 jsx快了近3倍。
可能有人会说为什么要折腾这些?我想说的是 人类对效率的追求总是无止境的,正是像这样的折腾铸就了人类宏伟的科技蓝图。也希望我的一点贡献能抛砖引玉激发起大家的兴趣尝试一下

备注: jsv-compiler

是 jsv 而不是 jsx:这可能是尤雨溪更想要的vue代码编写方式相关推荐

  1. this指向、数据双向流、传递参数、JSX中循环、React中样式、路由、引入资源的其它方式、create-react-app脚手架、事件处理、获取数据、UI框架推荐、pc桌面应用electronjs

    改变this指向的几种方式: //1.使用箭头函数代替原始函数写法:getState=()=>{}//2.在函数调用时给函数名加bind(this)方法:(bind中第一个参数表示修改this指 ...

  2. 面试题:为什么索引要使用B+树而不使用其他索引?以及B+树为什么更矮胖

    1.为什么要使用B+树做索引而不适用别的作为索引? 2.为什么B+树更加矮胖? 因为B+树一个节点能存放更多信息

  3. sublime jsx html插件,Sublime Text3关于react的插件——react语法提示代码格式化

    背景: 最近因为项目准备迁移切换技术栈到react~所以研究了一波sublime关于react的插件,很多推荐已经写得很详细,这里就补充一下语法提示和代码格式化的插件. 1.sublime-react ...

  4. android 图标拖动不了,拖动式选项卡(仿android) 添加了上下拉刷新后,下拉即刷新,而不是滚动到顶后再刷新,同时还想问一下正在刷新的图标怎么移到选项卡下...

    这是我的HTML代码 .mui-control-content { background-color: white; min-height: 600px; } .mui-control-content ...

  5. Vue 3拖更,尤雨溪介绍最新进展

    Vue.js 作者尤雨溪近日介绍了 Vue 3 的最新进展. 尤雨溪表示,由于在 Vue 3 上花费的大部分时间都投入到了设计和构建稳定的内核上,不过要让整个框架处于"ready" ...

  6. Vue 3 最新进展

    Vue.js 作者尤雨溪近日介绍了 Vue 3 的最新进展. 尤雨溪表示,由于在 Vue 3 上花费的大部分时间都投入到了设计和构建稳定的内核上,不过要让整个框架处于"ready" ...

  7. vue和react对比

    模板 vs JSX React与Vue最大的不同是模板的编写.Vue鼓励你去写近似常规HTML的模板.写起来很接近标准HTML元素,只是多了一些属性. <ul>    <templa ...

  8. vue和react哪个开发效率高,vue 和 react 哪个前景好

    react和vue哪个比较好 vue比较好.VUE是 iOS 和 Android 平台上的一款Vlog社区与编辑工具,允许用户通过简单的操作实现Vlog的拍摄.剪辑.细调.和发布,记录与分享生活. 还 ...

  9. Vue和React的区别

    笔者就直入正题:相信大家都知道什么是vue和react; 那么我们从数据双向绑定.组件及数据流.路由.状态管理等方面来分别对比一下怎样去使用Vue和React. 数据双向绑定 何为数据双向绑定:Vie ...

  10. Vue与React两个框架的区别和优势对比

    Vue与React两个框架的区别和优势对比 Vue和React两个JavaScript框架都是当下比较受欢迎的,他们两者之间的区别有哪些,各自的优缺点是什么,本文将为你呈现. 我已经写出了两个几乎一样 ...

最新文章

  1. 大学生计算机基础excel视频,大学生计算机基础Excel.doc
  2. 抽象:程序员必备的能力
  3. C语言输入end时结束程序,给大家一个程序,输入多个字符串以END结束后排序,这个程序运行,即结果都是对的。...
  4. 3层vni vxlan_VXLAN技术:三层网络构建虚拟的二层网络
  5. 【漫画】程序猿 996 会猝死,而企业家 007 却不会?
  6. MySql详解(六)
  7. 作者:张丹(1991-),女,中南大学信息与工程学院硕士生。
  8. 统计测序数据reads数和碱基数的几种方法
  9. mysql8 修改密码_Mysql 8新特性之(1):账户与安全更人性化
  10. 《教孩子编程(Python语言版)》课程介绍
  11. linux用于开发qt java_Linux下Qt程序的打包发布
  12. c语言flappy bird代码,Flappy bird源代码(略吊)
  13. 【CSS3】---last-of-type选择器+nth-last-of-type(n)选择器
  14. webuploader横向按钮样式
  15. 基于DWM1000模块开发UWB系统进行室内定位
  16. Java|二叉树基础详解
  17. j2sdk_5_0.exe的使用
  18. verilog prbs
  19. 解决Linux系统centos7的开机报错:Welcome to emergency mode
  20. DTI脑网络构建 详细介绍处理过程以及PANDA的使用

热门文章

  1. 机器学习笔记(三)——归一化、KD树、数值型特征无量纲化、数值型特征分箱等
  2. linux之ls -l命令详解
  3. 【JZOJ6124】有限空间跳跃理论
  4. e4a浏览框本地HTML,E4A浏览器 · E4A易安卓中文开发教程-E4A社区 · 看云
  5. 取次花丛懒回顾,半缘修道半缘君
  6. 整数 (Integer)
  7. NX二次开发-UFUN输入对象获得对象所在的部件tag UF_OBJ_ask_owning_part
  8. php退款,PHP实现微信申请退款流程的方法
  9. 强大的 Stream 函数式编程
  10. 高德地图api的自定义地点标注