是 jsv 而不是 jsx:这可能是尤雨溪更想要的vue代码编写方式
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 */)]))}
})()
- 为了保留 hoisted 特性,编译后的结果是一个自执行函数,返回渲染函数。利用闭包特性,仍然可以取到_hoisted_1;
- 为了使用当前作用域的变量 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代码编写方式相关推荐
- this指向、数据双向流、传递参数、JSX中循环、React中样式、路由、引入资源的其它方式、create-react-app脚手架、事件处理、获取数据、UI框架推荐、pc桌面应用electronjs
改变this指向的几种方式: //1.使用箭头函数代替原始函数写法:getState=()=>{}//2.在函数调用时给函数名加bind(this)方法:(bind中第一个参数表示修改this指 ...
- 面试题:为什么索引要使用B+树而不使用其他索引?以及B+树为什么更矮胖
1.为什么要使用B+树做索引而不适用别的作为索引? 2.为什么B+树更加矮胖? 因为B+树一个节点能存放更多信息
- sublime jsx html插件,Sublime Text3关于react的插件——react语法提示代码格式化
背景: 最近因为项目准备迁移切换技术栈到react~所以研究了一波sublime关于react的插件,很多推荐已经写得很详细,这里就补充一下语法提示和代码格式化的插件. 1.sublime-react ...
- android 图标拖动不了,拖动式选项卡(仿android) 添加了上下拉刷新后,下拉即刷新,而不是滚动到顶后再刷新,同时还想问一下正在刷新的图标怎么移到选项卡下...
这是我的HTML代码 .mui-control-content { background-color: white; min-height: 600px; } .mui-control-content ...
- Vue 3拖更,尤雨溪介绍最新进展
Vue.js 作者尤雨溪近日介绍了 Vue 3 的最新进展. 尤雨溪表示,由于在 Vue 3 上花费的大部分时间都投入到了设计和构建稳定的内核上,不过要让整个框架处于"ready" ...
- Vue 3 最新进展
Vue.js 作者尤雨溪近日介绍了 Vue 3 的最新进展. 尤雨溪表示,由于在 Vue 3 上花费的大部分时间都投入到了设计和构建稳定的内核上,不过要让整个框架处于"ready" ...
- vue和react对比
模板 vs JSX React与Vue最大的不同是模板的编写.Vue鼓励你去写近似常规HTML的模板.写起来很接近标准HTML元素,只是多了一些属性. <ul> <templa ...
- vue和react哪个开发效率高,vue 和 react 哪个前景好
react和vue哪个比较好 vue比较好.VUE是 iOS 和 Android 平台上的一款Vlog社区与编辑工具,允许用户通过简单的操作实现Vlog的拍摄.剪辑.细调.和发布,记录与分享生活. 还 ...
- Vue和React的区别
笔者就直入正题:相信大家都知道什么是vue和react; 那么我们从数据双向绑定.组件及数据流.路由.状态管理等方面来分别对比一下怎样去使用Vue和React. 数据双向绑定 何为数据双向绑定:Vie ...
- Vue与React两个框架的区别和优势对比
Vue与React两个框架的区别和优势对比 Vue和React两个JavaScript框架都是当下比较受欢迎的,他们两者之间的区别有哪些,各自的优缺点是什么,本文将为你呈现. 我已经写出了两个几乎一样 ...
最新文章
- 大学生计算机基础excel视频,大学生计算机基础Excel.doc
- 抽象:程序员必备的能力
- C语言输入end时结束程序,给大家一个程序,输入多个字符串以END结束后排序,这个程序运行,即结果都是对的。...
- 3层vni vxlan_VXLAN技术:三层网络构建虚拟的二层网络
- 【漫画】程序猿 996 会猝死,而企业家 007 却不会?
- MySql详解(六)
- 作者:张丹(1991-),女,中南大学信息与工程学院硕士生。
- 统计测序数据reads数和碱基数的几种方法
- mysql8 修改密码_Mysql 8新特性之(1):账户与安全更人性化
- 《教孩子编程(Python语言版)》课程介绍
- linux用于开发qt java_Linux下Qt程序的打包发布
- c语言flappy bird代码,Flappy bird源代码(略吊)
- 【CSS3】---last-of-type选择器+nth-last-of-type(n)选择器
- webuploader横向按钮样式
- 基于DWM1000模块开发UWB系统进行室内定位
- Java|二叉树基础详解
- j2sdk_5_0.exe的使用
- verilog prbs
- 解决Linux系统centos7的开机报错:Welcome to emergency mode
- DTI脑网络构建 详细介绍处理过程以及PANDA的使用
热门文章
- 机器学习笔记(三)——归一化、KD树、数值型特征无量纲化、数值型特征分箱等
- linux之ls -l命令详解
- 【JZOJ6124】有限空间跳跃理论
- e4a浏览框本地HTML,E4A浏览器 · E4A易安卓中文开发教程-E4A社区 · 看云
- 取次花丛懒回顾,半缘修道半缘君
- 整数 (Integer)
- NX二次开发-UFUN输入对象获得对象所在的部件tag UF_OBJ_ask_owning_part
- php退款,PHP实现微信申请退款流程的方法
- 强大的 Stream 函数式编程
- 高德地图api的自定义地点标注