【vue vapor jsx 未雨绸缪】

随着vue3.6.0 alpha的发布,vapor mode进入正式版本只是时间上的问题,可以预见的是各个组件库都将积极适配vapor,这篇文章主要侧重vue中使用jsx而非SFC,所以不涉及template相关。目前vue官方也是提供了vue-jsx-vapor这个仓库,处于v2.5.4-beta.1阶段,而vue3发布以来使用jsx的插件为 @vitejs/plugin-vue-jsx,依赖的是vue官方仓库的babel-plugin-jsx,不知道后面会不会直接用vapo jsx还是说两种jsx开发方式并行,ant-deisgn-vue仓库已经将适配vapor mode提上了日程,对于ant-design-vue这种全部由jsx构建的组件库,感觉适配的工作量会很大,对于参与开源有兴趣的朋友可以关注一下

// 获得编译器宏和指令的类型提示
vscode 中安装 ts-macro 插件,项目中安装 `@ts-macro/tsc` 来替代 `tsc` 进行类型检查// package.json
{"scripts": {"typecheck": "tsmc --noEmit"// ...}
}

一、变化1:组件定义

// 原
export default defineComponent({name: 'xx',setup(props, { attrs, slots, emit, expose }) {return () => <Comp />}
})// vapor jsx
export default defineVaporComponent((props) => {const attrs = useAttrs()const slots = useSlots()const model = defineModel()defineExpose({...})return <Comp />
})
// 以及下面两种形式
export default defineComponent(() => {// ...同上return <Comp />
})
export default () => {// ...同上return <Comp />
}

vue-jsx-vapor 支持 Virtual DOM 和 Vapor DOM 混合使用。将 interop 设置为 true 后,在 defineVaporComponent 中定义的 JSX 会被编译为 Vapor DOM, 在 defineVaporComponent 外定义的 JSX 会被编译为 Virtual DOM

// vite.config.ts
import { defineConfig } from 'vite'
import vueJsxVapor from 'vue-jsx-vapor/vite'export default defineConfig({plugins: [vueJsxVapor({interop: true,}),],
})

二、变化2:编译器宏

  1. 前置条件:需要手动开启marcos
// vite.config.ts
import { defineConfig } from 'vite'
import vueJsxVapor from 'vue-jsx-vapor/vite'
export default defineConfig({plugins: [vueJsxVapor({ macros: true })]
})// ts-macro.config.ts
import vueJsxVapor from 'vue-jsx-vapor/volar'
export default {plugins: [ vueJsxVapor({ macros: true })],
}
  1. defineModel
    手动挡和自动挡的区别,vapor中如果需要触发外层事件这种,按照相关issue来看应该是不会做defineEmits宏,所以需要通过props拿到事件,如onChange?.(data),就相当于emit(‘change’, data)这种触发形式了
// 假设
<comp v-model="data" />// 原export default defineComponent({emits: ['update:modelValue'],setup(props, { emit }) {emit('update:modelValue', xx)return ...}
})// vapor jsx, 与SFC使用一致
export default defineComponent(() => {const model = defineModel()model.value = xxreturn ...
})
  1. defineSlots
// 原
export default defineComponent({slots: Object as SlotsType<{default: any}>,setup(props, { slots }) {return () => (<div>{ slots.default?.() } </div>)}
})// vapor jsx,与SFC使用有一点差异
export default defineComponent(() => {const slots = defineSlots({default: () => <div>default</div>})return (<slots.default />)
})
  1. defineExpose
// 原
export default defineComponent({setup(props, { expose }) {expose({a: 'xx'})return ...}
})// vapor jsx, 与SFC使用一致
export default defineComponent(() => {defineExpose({a: 'xx'})return ...
})
  1. defineStyle
    这个比较厉害,支持 CSS 变量和 JS 变量绑定;支持在文件中定义多个样式宏;支持多个 CSS 预处理器:cssscsssasslessstyluspostcss;在函数内部定义则scope选项默认为true;支持css-modules
defineStyle(`.red {color: red;}  
`)
defineStyle.css({...})
defineStyle.scss({...})
defineStyle.less({...})
defineStyle.stylus({...})// css-modules
const styles = defineStyle.scss(`.foo { color: blue;.bar { background: red;}}
`)<div class={styles.foo} />

三、变化3:内置指令

  1. v-if、v-else-if、v-else
    老版中简单的条件可以用v-show,稍微复杂一点的可以用三元表达式,再稍微复杂点还可以三元表达式套娃
// 是的老版也提供了一些内置指令支持
export default defineComponent({setup() {return () => (<><div v-show={isVisible} />{// 或}{isStatus ? <CompA /> : <CompB />}</>)}
})// vapor jsx,使用与SFC基本一致
export default defineComponent(({ count = 0! }) => {return (<fieldset><legend>If</legend><div v-if={count === 0}>eq {count}</div><div v-else-if={count > 0}>lg {count}</div><div v-else>lt {count}</div></fieldset>)
})
  1. v-for
// 原
<div>
{ data.map((item, index) => {return (<div key={index}>{item}</div>)}) 
}
</div>// vapor jsx,与SFC使用基本一致
export default () => (<div v-for={(item, index) in 4} key={index}>{item}</div>
)
  1. v-slot、v-slots
// 原
export default defineComponent({slots: Object as SlotsType<{default: any}>,setup(props, { slots }) {// 取插槽传递的值return () => (<Child v-slots={{ default: (data) => <div>{data}</div> }>)/ 向子组件传递插槽return () => (<Child v-slots={slots}>)// 或者return () => (<Child v-slots={{ default: slots.default }>)// 或者return () => (<Child>{ slots.default?.() }</Child>)// 亦或者return () => (<Child><Comp /></Child>)}
})// vapor jsx,新增了v-slot,
export default defineComponent(({ count = 0! }) => {return (<>// 取插槽传递出的值<ChildA v-slot={{ foo }}>{{ foo }}</ChildA>// 向子组件传递插槽<ChildB v-slots={{ title: xx }} /></>)
})
  1. v-model
    babel-plugin-jsx还提供过v-models,但1.1.0版本过后不推荐使用,这里就不再提,vapor jsx也不支持v-models,这个指令两个版本使用差别不大,vapor jsx拓展了动态属性与修饰符的用法
// 原
<input v-model={val} />
<input v-model:argument={val} />
<input v-model={[val, ['modifier']]} />
// 或者
<input v-model_modifier={val} />
<A v-model={[val, 'argument', ['modifier']]} />
// 或者
<input v-model:argument_modifier={val} />// vapor jsx
<imput v-model={val} />
<input v-model:argument={val} />
// 动态参数,因为jsx不支持数组表达式,所以用$代替,即`$name$`这种形式
<input v-model:$name$={foo} /> // 等同于SFC <input v-model['name']="foo" />
// 修饰符,因为jsx不支持.关键字,所以用下划线_代替
<input v-model_number={value} /> // 等同于SFC <input v-model.number="value" />

总结

vue之前的jsx的整体结构更偏向于options API,虽然在setup中用的都是composition API,这种算是承接了vue2到vue3的转变,开发体验也比较向react jsx的方向靠拢,新的vapor jsx则是减少了与 SFC 使用的割裂感,将编译器宏、内置指令也带到了jsx开发中,降低了上手难度,也许会吸引到更多的用户来体验在vue中使用jsx开发

特性JSX (babel-plugin-jsx)Vapor JSX (vue-jsx-vapor)
组件定义setup() 返回渲染函数直接返回JSX
编译器宏不支持defineXxx 系列
指令支持仅基础指令(v-show)常用指令(v-if/v-for等)
插槽系统v-slotsv-slotv-slots
样式处理传统CSS方案defineStyle

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/93189.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/93189.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

go语言数据结构与排序算法

package mainimport "fmt"func main() {Bubble_Sort()Select_Sort()Insert_Sort()Shell_Sort()Heap_Sort()Merge_Sort()Quick_Sort() }一、1、冒泡排序 // 冒泡排序 func Bubble_Sort() {str : []int{9, 1, 5, 8, 3, 7, 4, 6, 2}// 正向冒泡for i : 0; i < len(st…

Petalinux生成文件的关系

1. 生成文件概述BOOT.BIN是引导程序&#xff0c;包括了 u-boot.elf是build u-boot生成的zynq_fsbl.elf&#xff08;引导PS和PL的启动&#xff09;elf文件是和启动引导相关的文件image.ub是镜像文件roofs.cpio.gz用来构建根文件系统

MongoDB的操作

在 Java 中操作 MongoDB 的 增删改查&#xff08;CRUD&#xff09; 主要有两种方式&#xff1a; Spring Data MongoDB&#xff08;推荐&#xff0c;类似 JPA 风格&#xff09;MongoDB Java Driver&#xff08;原生 API&#xff0c;更灵活&#xff09;1. Spring Data MongoDB 方…

getConnectionOwnerUid

在Android系统中&#xff0c;为了进行网络权限控制、流量统计等&#xff0c;需要将网络连接&#xff08;如Socket&#xff09;与发起该连接的应用UID关联起来。这种关联通常在内核中建立&#xff0c;并在用户空间通过一些接口进行查询。 1. 内核中的实现基础 Linux内核中&#…

开源 Arkts 鸿蒙应用 开发(十)通讯--Http数据传输

文章的目的为了记录使用Arkts 进行Harmony app 开发学习的经历。本职为嵌入式软件开发&#xff0c;公司安排开发app&#xff0c;临时学习&#xff0c;完成app的开发。开发流程和要点有些记忆模糊&#xff0c;赶紧记录&#xff0c;防止忘记。 相关链接&#xff1a; 开源 Arkts …

net8.0一键创建支持(RabbitMQ)

Necore项目生成器 - 在线创建Necore模板项目 | 一键下载 RabbitMQController.cs using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using RabbitMQ.Client; using RabbitMQ.Client.Events; using System.Text; using System.Threading.Tasks; using UnT.Tem…

Rust 泛型与特性

Rust 泛型与特性 引言 Rust 语言以其安全性和高效性在编程语言中独树一帜。Rust 的泛型和特性是其核心特性之一,它们使得开发者能够编写更加通用、灵活且安全的代码。本文将深入探讨 Rust 中的泛型和特性,包括其概念、用法以及在实际开发中的应用。 泛型简介 概念 泛型是…

LangChain学习——结构化输出和数据解析

LangChain 本指南全面介绍LangChain中结构化输出生成和数据解析的核心功能&#xff0c;包括Pydantic BaseModel构造、各种输出解析器的使用&#xff0c;以及高级错误处理机制。 详细测试样例和代码可参考如下两个链接&#xff1a; test_output_parserstest_pydantic_base_mo…

基于华为ENSP的BGP的状态机深入浅出

本篇技术博文摘要 &#x1f31f; 本文章主要探讨BGP状态机如何控制BGP连接的建立与维护&#xff0c;以及BGP协议在运行过程中如何交换路由信息并确保网络的稳定性 引言 &#x1f4d8; 在这个快速发展的技术时代&#xff0c;与时俱进是每个IT人的必修课。我是肾透侧视攻城狮&…

Android 15中的16KB大页有何优势?

deepseek回答&#xff1a; Android 15引入的16KB大内存页是系统性能优化的关键变革&#xff0c;其核心优势体现在以下方面&#xff1a; ⚡ 一、性能全面提升 系统整体加速 配置16KB页面的设备整体性能提升5%-10%&#xff0c;通过减少内存管理开销释放更多资源用于应用运行。…

Gis数据的A*算法规划航线

1.1 用到的技术栈geotools JTSJgrapht1.2 实现思路// 定义栅格网格参数private static final double CELL_SIZE_DEGREES 0.005;private static int gridWidth 0;//格子高度 index 1private static int gridHeight 0;//格子宽度// 1. 读取GeoJSON文件File geoJsonFile new …

Spring Boot 默认使用 CGLIB,但CGLIB 无法代理 final 类或 final 方法

那么当这两件事冲突时&#xff0c;Spring Boot 是怎么“解决”的呢&#xff1f;答案是&#xff1a;它不解决&#xff0c;也无法解决。当这种情况发生时&#xff0c;你的应用程序会直接启动失败。这不是 Spring Boot 的疏忽&#xff0c;而是由 CGLIB 的底层原理和 Java 语言的规…

cuda编程笔记(10)--memory access 优化

全局内存访问优化&#xff08;Coalesced Access&#xff09; 什么是 Coalesced Access&#xff1f; 定义&#xff1a;一个 warp&#xff08;32 个线程&#xff09;在同一指令中访问全局内存时&#xff0c;如果这些访问请求可以合并成尽可能少的内存事务&#xff08;通常是 32…

闲庭信步使用图像验证平台加速FPGA的开发:第三十一课——车牌识别的FPGA实现(3)车牌字符分割预处理

&#xff08;本系列只需要modelsim即可完成数字图像的处理&#xff0c;每个工程都搭建了全自动化的仿真环境&#xff0c;只需要双击top_tb.bat文件就可以完成整个的仿真&#xff0c;大大降低了初学者的门槛&#xff01;&#xff01;&#xff01;&#xff01;如需要该系列的工程…

电子电气架构 --- 汽车软件全生命周期

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活,除了生存温饱问题之外,没有什么过多的欲望,表面看起来很高冷,内心热情,如果你身…

力扣面试150(41/150)

7.25 56. 合并区间 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 我的思路&#xff1a; 左端点升序…

【隧道篇 / IPsec】(7.6) ❀ 01. 利用向导快速建立IPsec安全隧道 (点对点) ❀ FortiGate 防火墙

【简介】相信很多人已经习惯利用导向快速创建VPN了&#xff0c;而且已经有部分尝鲜者已经用上了FortiOS 7.6&#xff0c;但是会发现FortiOS 7.6下的VPN向导改变了很多&#xff0c;一时无法下手&#xff0c;下面我们来看看最常见的点对点是如何配置的。环境介绍在配置IPsec VPN之…

PLLIP核

。1 号红色框内的速度等级代表着设备的速度 等级&#xff0c;保存默认就好&#xff1b;2 号红色框内设置输入频率&#xff1b;3 号红色框选择 PLL 的工作模式。我们 开发板用的晶振是 50MHz 的&#xff0c;故在 2 号红色框内我们填写 50MHz&#xff1b;我们在 3 号红色框内选正…

1.1 Deep learning?pytorch ?深度学习训练出来的模型通常有效但无法解释合理性? 如何 解释?

DL 是什么&#xff0c;你如何理解DL模型&#xff1f; DL 对于我而言&#xff0c;就是人类试图想通过数学语言描述人类学习过程的一门技术&#xff0c;或者说学科。 因此 DL 模型 相当于 数学 的 一个 funciton &#xff0c;有输入&#xff0c;通过function处理&#xff0c;得…

java实现在工具类中注入其他对象方式

方案1&#xff1a; Slf4j Component public class ChatdocApiClient {Value("${chatdoc.app-id}")private String appId;Value("${chatdoc.secret}")private String secret;Value("${chatdoc.domain}")private String domain;private final Rest…