Vue3 JSX 插槽、v-model 的用法以及 React JSX 的区别

前言

写这篇文章的初衷是,Vue3 JSX 部分与 React JSX 容易混淆,比如如本文所说的 slot & v-model,
如果你是第一次接触 JSX,可先阅读前面写过的 React & JSX 日常用法与基本原则 来对 JSX 有一个整体的认知以及比较两者间的差异。

一、什么是 JSX

JSX 是用一种可以将 HTML + JS 混合写的一种语法糖,最初由 React 率先研发,后来 Vue3 也借鉴了这种写法灵感实现自家的 JSX

实际上,能够快速研发 JSX 还得得益于一款叫做由 @babel/plugin-syntax-jsx 的插件,
是由 Babel 研发的,它只负责解析但不负责转换,于是 ReactVue3 基于此插件实现了自家的 JSX

举个例子

const Component = () => <div> {[1,2,3].map((num) => <span>{num}</span>)} </div>
// 等价于 <div><span>1</span><span>2</span><span>2</span></div>

这种写法就叫 JSX,换句话说,只要你用过 React/Vue3 其中的 JSX ,你就同时掌握了两种框架的 JSX 。当然,每个框架对自己的 JSX 都喜欢添砖加瓦,如独特的 API,独特的属性修饰符;
但万变不离其宗, HTML + JS 写法是任何 JSX 框架统一遵循规范的不变事实。

二、Vu3 使用 JSX

2.1 准备工作

a) 针对新项目

使用官方提供的安装命令,里面内置了 JSX、TypeScript 等插件,无须手动配置

npm init vue@latest

按照提示选项勾选即可,请添加图片描述
接下来就可以愉快的使用 JSX 和 TypeScript ~

b) 针对现有项目

  1. 安装 JSX 依赖包:
npm install @vue/babel-plugin-jsx -D
  1. 新建 Babel 配置文件: babel.config.json ,内容如下:
{"plugins": ["@vue/babel-plugin-jsx"]
}

然后就可以愉快的使用 JSX 啦~

对有关 Babel 的概念感兴趣的可参考前面写过的:
JS & 介绍 Babel 的使用及 presets & plugins 的概念

2.2 使用 slot 插槽

定义插槽方式1

// NavBar.jsx
import { defineComponent } from 'vue'
const NavBar = defineComponent({setup(props, { slots }) {return () => {return (<><div>Simple</div><div> { slots?.default() } </div><header> { slots?.header() } </header></>)}}
})

注意,使用 slot 时,setup return 必须是一个函数,实际上就是 render() 。

定义插槽方式2

// NavBar.jsx
const NavBar = (props, { slots }) => {return (<><div>Simple</div><div> { slots?.default() } </div><header> { slots.header() } </header></>)
}

这两种定义方式的区别取决于你是否需要用到 Vue 提供的一些钩子函数或响应式 API,比如第一种有 setup ,如果是纯普素的组件,使用第二种方式即可。

使用插槽方式1:双括号

// App.jsx
import NavBar from '@/components/nav-bar'
const App = () => {return (<><NavBar>{{default: () => 'Hello,world.',header: () => 'Hello, header.'}}</NavBar></>)
}
export default App

使用插槽方式2:v-slots

// App.jsx
import NavBar from '@/components/nav-bar'
const App = () => {const slots = {default: () => 'Hello,world.',header: () => 'Hello, header.'}return (<><NavBar v-slots={slots}></NavBar></>)
}
export default App

使用插槽方式3:把它当成 .vue 文件使用即可

// App.vue
<template><div><NavBar>Hello, world.<template #header>Hello, header.</template></NavBar></div>
</template><script lang="ts">
import { defineComponent } from 'vue';
import NavBar from '@/components/nav-bar'
export default defineComponent({components: {NavBar},props: {},setup(props) {return {}}
})
</script>

提示:.vue 组件可以引入 .jsx/tsx 组件,反之 .jsx/tsx 也可以引入 .vue 组件,它们本质上就是一个 Object 。

2.3 使用 v-model

使用方式1:标签绑定 v-model

// NavBar.jsx
import { ref, defineComponent } from 'vue'
const NavBar = defineComponent({setup() {const phone = ref()return () => {return (<input type="text" v-model={phone.value} />) }}
})
export default NavBar;

使用方式2:组件绑定 v-model

// Card.jsx 引入 component 组件。
import { defineComponent, ref } from 'vue'
import Component from './component'const CardComponent = defineComponent({setup() {const componentName = ref()return () => {return (<main><Component v-model={[componentName.value, 'modelValue']} /></main>)}}
})
export default CardComponent// 定义组件 Component.jsx 。
import { defineComponent, toRefs } from 'vue'
const Component = defineComponent({emits: ['update:modelValue'],setup(props, { emit }) {return () => {return (<input type="text" onInput={($event) => emit('update:modelValue', $event.target.value)} />)}}
})
export default Component

解释:

  1. Card.jsx 引入 Component 组件并绑定 v-model
  2. v-model 的第二个参数 modelValue 与 Component 组件的 update:modelValue 成对应关系,是双向更新的必备定义条件。

使用方式3:组件绑定多个 v-model

// Card.jsx 引入 component 组件。
import { defineComponent, ref } from 'vue'
import Component from './component'const CardComponent = defineComponent({setup() {const componentName = ref()const modelPhoneNumber = ref()return () => {return (<main><Component v-model={[componentName.value, 'modelValue']} v-model={[modelPhoneNumber.value, 'modelPhoneNumber']} // 上面等同于下面。// v-model:modelValue={modelValue.value} // v-model:modelPhoneNumber={modelPhoneNumber.value} /></main>)}}
})
export default CardComponent// 定义组件 Component.jsx 。
import { defineComponent, toRefs } from 'vue'
const Component = defineComponent({emits: ['update:modelValue', 'update:modelPhoneNumber'],setup(props, { emit }) {return () => {return (<input type="text" onInput={($event) => emit('update:modelValue', $event.target.value)} /><input type="text" onInput={($event) => emit('update:modelPhoneNumber', $event.target.value)} />)}}
})
export default Component

提示:对于绑定 v-model 的组件来说,组件内无需再自定义 props: {},可别跟平时的传参给混淆了,如果组件内部确实要访问,则给组件加上 x={x} 然后用 props 接受即可。

2.4 支持 TSX 写法

TSX 指的是能够在 TypeScript 中写 JSX,在 tsconfig.json 中加以下选项:

"compilerOptions": {"jsx": "preserve"
}

接下来只需将文件后缀由 .jsx 改成 .tsx 即可。

2.5 注意事项

  1. 使用 JSX 语法时,文件名必须为 .jsx.tsx ,不支持 .vue
  2. 在 JSX 里的标签内访问响应式数据时,须带上 .value 访问。

三、Vue3 JSX 与 React JSX 的差别

  1. 绑定数据方式不同,Vue3 JSX 采用 v-model 双向绑定数据,React 采用 setState 。
  2. 生命周期函数不同。
  3. 插槽用法不同。
  4. 有各自的 API。

其实不管是 Vue3 or React,它们最大的特点就是 JSX ,本质上就是 HTML & JS 可以混合写,这才是它们的共同之处。

文献:
https://juju.one/using-jsx-with-vue3/
https://github.com/vuejs/babel-plugin-jsx

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

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

相关文章

架构重构|性能和扩展性大幅提升的Share Creators智能数字资产管理软件3.0

作为数字资产管理行业的领军者&#xff0c;Share Creators智能数字资产管理软件持续致力于帮助企业和团队智能化管理数字资产&#xff0c;提升工业化管线制作效率。经过本次重构&#xff0c;Share Creators 3.0版本重装上阵&#xff0c;全面更新的服务架构标志着软件整体性能的…

2023最新ChatGPT商业运营网站源码+支持ChatGPT4.0+新增GPT联网功能+支持ai绘画+实时语音识别输入+用户会员套餐+免费更新版本

2023最新ChatGPT商业运营网站源码支持ChatGPT4.0新增GPT联网功能支持ai绘画实时语音识别输入用户会员套餐免费更新版本 一、AI创作系统二、系统程序下载三、系统介绍四、安装教程五、主要功能展示六、更新日志 一、AI创作系统 提问&#xff1a;程序已经支持GPT3.5、GPT4.0接口…

磁盘镜像软件

什么是磁盘镜像 磁盘镜像是存储在计算机磁盘中的数据的副本或副本。磁盘镜像将包含数据存储设备的内容&#xff0c;并复制此类设备的结构。它还将包含操作系统分区。 磁盘镜像本质上是一种从主系统复制操作系统和存储在磁盘中的数据以将其分发到其他目标计算机的方法。自动化…

有源差分探头的电压限定和检查步骤

为了使传统示波器能够显示和测试高共模电压的电路波形&#xff0c;有源差分探头对示波器测量性能延伸到了电子功率变换器、 逆变器、 电机的速度控制、 开关电源和许多应用程序的测试。 差分探头外观构成&#xff1a; A-输出线&#xff1a;连接示波器的 BNC 输出连接头和辅助性…

Vscode——python代码调试时,列表(变量)内容显示不全的一种解决办法

一、情况描述 列表维度是(1080,1920)&#xff0c;但只能看到前500行&#xff0c;后面的看不到了。 二、解决办法1——添加到监视 右键变量&#xff0c;选择 添加到监视 编辑表达式 三、解决办法2——数据查看器中查看值 右键变量&#xff0c;选择 在数据查看器中查看值&…

瑞吉外卖-Day02

title: 瑞吉外卖-Day02 abbrlink: ‘1’ date: 2023-04-1 19:30:00 瑞吉外卖-Day02 课程内容 完善登录功能新增员工员工信息分页查询启用/禁用员工账号编辑员工信息 分析前端页面效果是如何实现的 为什么点击左边 右边会根着变化 [外链图片转存失败,源站可能有防盗链机制…

nodejs-pm2管理js并发/自动重启/恢复等

目录 一、nodejs安装二、启动运行js三、实用功能1-pm2对进程名起别名四、实用功能2-pm2启动多个进程五、实用功能3-pm2内存限制自动重启六、实用功能4-服务器宕机前保存记录恢复进程 一、nodejs安装 nodejs安装使用nohup后台启动项目&#xff0c;倒是解决了控制台问题&#xf…

高适的逆袭之路

骆宾王7岁咏鹅&#xff0c;王勃10岁写论文&#xff0c;王维18岁名震天下。 高适50岁才步入仕途。 父亲官居刺史&#xff0c;祖父正三品还封了平原郡公&#xff0c;拿着将门虎子剧本的高适&#xff0c;却因父亲早逝&#xff0c;荣耀和显赫已成过往云烟。能握住的&#xff0c;是…

JUC--CompletableFuture下

对计算速度进行选用 import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit;public class Test4 {public static void main(String[] args) {CompletableFuture<String> a CompletableFuture.supplyAsync(() -> {try { TimeUnit.SE…

Django之ORM的锁,开启事务,Ajax

一、行锁 select_for_update(nowaitFalse, skip_lockedFalse) 注意必须用在事务里面&#xff0c;至于如何开启事务&#xff0c;我们看下面的事务一节 Book.objects.select_for_update().filter(nid3) # 锁住nid3的行select_for_update中的两个参数了解即可&#xff0c;因为在…

基于单片机的智能窗帘智能晾衣架系统的设计与实现

功能介绍 以STM32单片机单片机作为主控系统&#xff1b;OLED液晶显示当前环境温湿度&#xff0c;光照强度&#xff0c;时间&#xff0c;开关状态等信息&#xff1b;雨滴传感器检测当前环境是否下雨&#xff0c;天气下雨检测&#xff0c;天气潮湿时自动收衣服&#xff1b;可以通…

文心一言 VS 讯飞星火 VS chatgpt (54)-- 算法导论6.2 6题

文心一言 VS 讯飞星火 VS chatgpt &#xff08;53&#xff09;-- 算法导论6.2 5题 六、证明:对一个大小为 n的堆&#xff0c;MAX-HEAPIFY 的最坏情况运行时间为 Ω(Ign)。(提示对于n个结点的堆&#xff0c;可以通过对每个结点设定恰当的值&#xff0c;使得从根结点到叶结点路径…