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

news2024/11/17 3:28:14

前言

写这篇文章的初衷是,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.coloradmin.cn/o/707483.html

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

相关文章

如何了解(海外抖音TiKToK)与国内抖音的区别以及介绍

一、海外抖音TK平台的优势 自从抖音在中国大受欢迎后&#xff0c;海外也推出了海外版抖音TK平台。尽管两者都是视频分享平台&#xff0c;但它们在一些方面具有明显的区别和独特的优势。下面将详细介绍海外抖音TK平台的优势以及与国内抖音的区别性。 优势&#xff1a; 1. 多元…

9-2 小波滤波器、去噪、增强、变换(matlab程序)

1.简述 小波去噪滤波算法是一种基于小波变换的滤波方法&#xff0c;它通过对信号进行小波变换来分解信号的频率分量&#xff0c;并根据信号的特点选择合适的阈值处理方法来去除噪声。该算法的主要思想是将信号分解成多个频率分量&#xff0c;根据信号的特点选择合适的阈值处理…

【IMX6ULL驱动开发学习】13.Pinctrl子系统与GPIO子系统

上一篇博客中&#xff0c;已经实现了设备树的添加 【IMX6ULL驱动开发学习】12.Linux驱动之设备树 这篇博客介绍Pinctrl子系统与GPIO子系统的使用 Pinctrl子系统参考文档&#xff1a; 内核文档链接&#xff1a;https://www.kernel.org/doc/Documentation/ 内核源码doc&#xff…

AD23 原理图选中元件在PCB中高亮显示

概述 项目需要&#xff0c;再次使用AD&#xff0c;在此做个笔录。 1、原理图界面 2、在原理图界面选中电容后&#xff0c;对应的PCB界面该电容高亮显示 3、总结 希望能帮助到有需要的攻城狮。

Linux查看日志常用操作整理

项目出现异常&#xff0c;要定位问题&#xff0c;查看日志是最常用的方法&#xff0c;在Linux系统查看一些日志文件&#xff0c;我们一般会使用tail、cat等命令&#xff0c;下面总结归纳一下这些常用的命令。 1、查看日志的方法 tail&#xff1a;tail命令应该是使用最多的&am…

探讨绿色照明与智能照明节能控制系统应用

张心志 安科瑞电气股份有限公司 上海嘉定 201801 【摘 要】随着社会经济的不断发展&#xff0c;人们对生活质量、环境品质越发重视。积极推广绿色智能照明&#xff0c;提高城市照明质量&#xff0c;对于改善人们居住环境意义重大。文章简要介绍了绿色照 明的基本要求、室内智…

互联网编程之简单邮箱发送程序

需求是使用Java写一个简单的邮箱发送程序。 注意需要到QQ邮箱的设置-账户中开启服务。 package org.example;import org.apache.commons.mail.Email; import org.apache.commons.mail.EmailException; import org.apache.commons.mail.SimpleEmail;public class Main {public …

ospf-interface-fsm-and-neighbor-fsm

/* Interface State Machine */ struct {int (*func) (struct ospf_interface *);int next_state; } ISM [OSPF_ISM_STATE_MAX][OSPF_ISM_EVEN

网络安全技术入门(1):简介

文章目录 1.前言2.什么是网络安全技术&#xff1f;3.列举一些常见的网络安全技术3.1 防火墙3.2 加密技术3.3 身份认证和访问控制3.4 恶意软件防护3.5 网络监控和日志管理3.6 威胁情报和漏洞管理3.7 安全培训和意识教育 4.网络安全研究的关键技术5.网络安全防护技术有哪些&#…

计算机网络 - 应用层http协议 - http报文格式介绍(1)

前言 本篇认识和理解应用层中的http协议&#xff0c;了解抓包工具并进行使用&#xff0c;认识请求报文与响应报文&#xff0c;了解报文中基本键值对意思例如&#xff1a;Set-Cookie, 状态码等&#xff0c;如有错误&#xff0c;请在评论区指正&#xff0c;让我们一起交流&#…

segement and remove-SAM一键清除物体(代码安装实战项目)

结果展示 去除图片中前景物体的步骤: 1.框选 2.分割 3.分离 4.去除 项目介绍 一键帮你剔除视频内的物体,现在只需要一句话。使用Meta的SAM技术,你现在可以让视频内任意物体消失! 特点 按照提示进行分割:只需输入“黑色狗”,您就可以将您的黑色狗分割出来; 修复图…

JAVA 初识序列化与反序列化

JAVA 初识序列化与反序列化 目录 JAVA 初识序列化与反序列化初识序列化与反序列化1 概述2 特点/应用场景3 涉及到的流对象4 代码实现序列化与反序列化4.1 步骤1&#xff1a;创建学生类Student4.2 步骤2&#xff1a;创建序列化测试类 5 测试报错NotSerializableException:6 测试…

yarn与npm的区别(yarn的安装报错问题)

一、yarn 是什么&#xff0c;yarn 与 npm 的区别是什么&#xff1f; yarn 是一个软件包管理系统&#xff0c;Yarn 和 npm 都是包管理工具&#xff0c;用于管理用 JavaScript 编写的软件包&#xff0c;yarn的出现是为了弥补 npm的一些缺陷。yarn 与 npm 的区别 &#xff1a; 性能…

Matplotlib---3D图

1. 3D图 # 3D引擎 from mpl_toolkits.mplot3d.axes3d import Axes3D fig plt.figure(figsize(8, 5)) x np.linspace(0, 100, 400) y np.sin(x) z np.cos(x)# 三维折线图 axes Axes3D(fig, auto_add_to_figureFalse) fig.add_axes(axes) axes.plot(x,y,z) plt.savefi…

arduino uno r3 机械臂

1、硬件 arduino uno r3 改进板、sg90舵机&#xff08;180度 x 4&#xff09;、JoyStick Shield PS2游戏摇杆扩展板&#xff08;或者按键 遥杆模块&#xff09;、3D打印件、M3螺丝螺母&#xff08;10mm 15mm 25mm &#xff09;以及M2螺丝螺母。 2、接线 开发版使用DC口7V-12V 供…

AI 绘画风格迁移之青铜模型训练

前情提要 2023-07-01 周六 杭州 阴 小记: mmp&#xff0c;上周吃烤面筋&#xff0c;不小心牙签扎到口腔&#xff0c;结果这几天吃什么都不舒服&#xff0c;可是计划还是要做的&#xff0c;下半年要把当下 AI 的应用梳理下&#xff0c;自己还是喜欢那种先使用再学习相关原理&a…

C语言之数组初阶(1-4)

目录 1. 一维数组的创建和初始化 2. 一维数组的使用 3. 一维数组在内存中的存储 4. 二维数组的创建和初始化 5. 二维数组的使用 6. 二维数组在内存中的存储 7. 数组越界 8. 数组作为函数参数 数组概念:数组是一组相同类型元素的集合 1.一维数组的创建和初始化 在C语言中…

【已解决】nacos新增配置报错: 发布失败。请检查参数是否正确

解决方法&#xff1a; sql文件直接采取容器默认自带的创建表&#xff0c;复制出来即可 非容器自带sql&#xff0c;有多余encrypted_data_key字段 1.删掉config_info 和 his_config_info 表中的encrypted_data_key字段 2.config_info 和 his_config_info 表中非空encrypted_data…

Android12之ServiceManager::addService注册服务的本质(一百五十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

如何用smardaten90天快速开发并上线智慧空间loT物联平台?

前言 大家好&#xff0c;我是小白白&#xff0c;前段时间一位好友接手了一个“烫手山芋”开发任务&#xff0c;77万㎡的科技园区需要打造智慧空间物联平台。要求接入600园区设备&#xff0c;处理15000日数据量&#xff0c;在打造整体IOT物联底座之上&#xff0c;构建起整个园区…