vue中的h函数与JSX语法

2023-11-04

vue不仅像react一样实现了jsx,而且还借助jsx发挥了javascript动态画的优势,了解学习jsx可以让你更灵活的开发需求。

一、 h函数

在聊vue中的JSX之前,需要简单介绍一下 h 函数,理解了 h 函数,会更好的理解JSX。

1.h函数概念

h()是一个用于创建VNode的实用程序,你可以理解为createVNode(),但因为它频繁的被使用,所以简称为h函数。

// @returns {VNode}
h(
    // {String | Object | Function} tag
    // 一个 HTML 标签名、一个组件、一个异步组件或一个函数式组件。
    // 必需的。
    'div',

    // {Object} props
    // 与 attribute、prop 和事件相对应的对象,这会在模板中用到。
    // 可选的(在开发时。建议传,实在没有传的时候,传入 null)
    {},

    // {String | Array | Object} children
    // 子 VNodes, 使用 `h()` 构建,
    // 或使用字符串获取 "文本 VNode" 或者
    // 有插槽的对象。
    //
    // 可选的。
    [
        'Some text comes first.',
        h('h1', 'A headline'),
        h(MyComponent, {
            someProp: 'foobar'
        })
    ]
)
//             这里不理解就先看下面的例子

2.理解h函数

在vue3的项目中,template是默认的写法,vue运行时会把template解析为render函数,之后,组件运行的时候通过render函数去返回h函数的运行结果去构造虚拟DOM

在这里插入图片描述
上面的图片是我随意运行了一个demo,打开vue调试工具得到的源码,_sfc_render 就是template解析成js之后的结果

所以在vue中,我们除了可以使用template写法之外,还可以直接写render函数

render函数跟h函数又有什么关系?

h函数的使用场景

下面先举一个小例子,有这样一个需求:通过一个变量(1~6)去渲染标题组件比的标签等级(h1~h6)。

如果我们使用template语法的话,利用v-if,可以实现出来,代码如下:

  <h1 v-if="num==1">{{title}}</h1>
  <h2 v-if="num==2">{{title}}</h2>
  <h3 v-if="num==3">{{title}}</h3>
  <h4 v-if="num==4">{{title}}</h4>
  <h5 v-if="num==5">{{title}}</h5>
  <h6 v-if="num==6">{{title}}</h6>

明显可以发现这样的代码太冗余,显得也很不专业,所以这里可以使用Vue中的h函数实现这个需求。

因为 render函数可以直接返回虚拟DOM,因而我们就不在需要template。在目录下新建一个文件Heading.jsx

Heading.jsx

import { defineComponent, h } from 'vue'

export default defineComponent({
  props: {
    level: {
      type: Number,
      required: true
    }
  },
  setup(props, { slots }) {
    return () => h(
      'h' + props.level, // 标签名
      {}, // prop 或 attribute
      slots.default() // 子节点
    )
  }
})

在上面的代码中,使用defineComponent定义一个组件,组件内部配置了propssetup,这里的setup函数的返回值也是一个函数,就是上面说的render函数,render函数返回的是h函数的执行结果。

然后,在主界面中,我们使用下面代码中的 import 语法来引入 Heading,之后使用 level 传递标签的级别,这样就实现了level与标签等级的同步

 <template>
  <Heading :level="3">hello geekbang</Heading>
</template>

<script setup>
import Heading from './components/Head.jsx'
</script>

运行:
在这里插入图片描述

手写h函数的优缺点

const p = h('p', {}, 'Hello, world!')

这个函数的优点是它可以简化创建 Virtual DOM 节点的过程,并且能够帮助开发人员避免拼写错误。它还可以自动将某些属性或属性值转换为合法的 HTML,从而帮助开发人员避免安全漏洞。

h 函数的缺点是它不够灵活。因为它是一个函数,所以无法提供额外的抽象层,因此无法像其他框架或库那样提供高级功能。

总的来说就是在复杂的场景中,h 函数写起来就显得非常繁琐,需要自己把所有的属性都转变成对象。并且组件嵌套的时候,对象也会变得非常复杂。

不过,因为 h 函数也是返回虚拟 DOM 的,所以有没有更方便的方式去写 h 函数呢?答案是肯定的,这个方式就是 JSX

JSX

JSX的概念

JSX 来源自 React 框架,他是一种 JavaScript 语法扩展,允许开发人员在 JavaScript 代码中写入类似于 HTML 的语法。

const button = <button type="button">Click me!</button>

上面的代码直接在 JavaScript 环境中运行时,会报错。

JSX 的本质就是下面代码的语法糖,h 函数内部也是调用 createVnode 来返回虚拟 DOM。在下面的内容中,对于那些创建虚拟 DOM 的函数,我们统一称为 h 函数。

const element = createVnode('h1',{id:"app"}, 'hello Geekbakg')

使用JSX

安装插件

npm install @vitejs/plugin-vue-jsx -D

配置babel,这里我需要打开 vite.config.js 文件去修改 vite 配置。

import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx';

export default defineConfig({
  plugins: [vue(),vueJsx()]
})

然后,我们进入 src/componentns/Heading.jsx 中,把 setup 函数的返回函数改成下面代码中所示的内容,

  setup(props, { slots }) {
    const tag = 'h'+props.level
    return () => <tag>{slots.default()}</tag>
  }

使用 JSX 的本质,还是在写 JavaScript,Element3 组件库设计中很多酒用到JSX,比如时间轴Timeline、表格Table等,时间轴Timeline中就有一个倒序渲染的属性,我们可以看一下它是怎么实现的

export const Timeline = (props)=>{
    const timeline = [
        <div class="start">8.21 开始自由职业</div>,
        <div class="online">10.18 专栏上线</div>
    ]
    if(props.reverse){
        timeline.reverse()
    }
    return <div>{timeline}</div>
}

通过数组的 reverse 方法直接进行数组反转,实现逆序渲染。类似这种动态性要求很高的场景,template 是较难实现的。

三、JSX 和 Template的区别

仔细思考,vue中的模版语法,实现的都是固定场景的需求,例如v-if、v-for,若遇到了有多种渲染逻辑的复杂场景,这个时候用v-if就无法满足了,而 JSX 只是 h 函数的一个语法糖,本质就是 JavaScript,想实现条件渲染可以用 if else,也可以用三元表达式,还可以用任意合法的 JavaScript 语法。

1. JSX 可以支持更动态的需求。而 template 则因为语法限制原因,不能够像 JSX 那样可以支持更动态的需求。
2.JSX 可以在一个文件内返回多个组件

export const Button = (props,{slots})=><button {...props}>slots.default()</button>
export const Input = (props)=><input {...props} />
export const Timeline = (props)=>{
  ...
}

总的来说,一般情况就使用tamplate模版语法,动态性要求较高的组件使用JSX实现

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

vue中的h函数与JSX语法 的相关文章

随机推荐

  • Rocketmq-- RocketMQ4.X基础介绍

    一 阿里开源消息队列 RocketMQ4 x介绍和新概念讲解 Apache RocketMQ作为阿里开源的一款高性能 高吞吐量的分布式消息中间件 1 1 特点 支持Broker和Consumer端消息过滤 支持发布订阅模型 和点对点 支持拉
  • Excel Row函数和Rows函数的使用方法,含Row(A:A)与Row(1:1)实例

    在 Excel 中 Row函数用于返回单元格的行号 Rows函数用于返回数组或引用单元格的行数 如果Row函数省略参数 默认返回公式所在单元格的行号 Rows函数不能省略参数 Rows函数常与Indirect函数 Index函数 If函数
  • 20230314-近视的小张

    1 题目名称 近视的小张 时间限制 1000ms内存限制 256M 题目描述 小张和他的 M 个朋友来到了一个十分神奇的地方 在这里有 N 个 柱子 对于每个 1 lt i lt N 第 i 个柱子都有两个属性 H i P i H i 表示
  • tasklet与workqueue的区别及底层实现区别

    softirq和tasklet都属于软中断 tasklet是softirq的特殊实现 workqueue是普通的工作队列 1 softirq 软中断支持SMP 同一个softirq可以在不同的CPU上同时运行 softirq必须是可重入的
  • Zabbix 如何动态执行监控采集脚本

    在使用Zabbix自定义脚本采集监控数据的时候 通常会遇到以下一些问题 服务器扩容之后 监控脚本如何部署到新的服务器上 监控脚本需要修改时 如何自动修改所有相同的监控脚本 如何备份监控采集脚本避免因服务器异常后丢失 新部署自定义监控 如何避
  • 能通过一张照片(2D)得到3D的模型吗?

    如下内容已经整理成 PDF 很好奇其实如果将人眼所看到的画面保存下来 拍照 人类是可以感知照片内的各个物体 是不是可以理解成这是一种2D到3D认知的转换 作者 知乎用户 链接 https www zhihu com question 529
  • win7蓝屏报错:STOP:0x0000007E

    报错环境 win 7 报错信息 STOP 0x0000007E 解决办法 0X0000007E代码的意思是电脑中病毒了或是电脑内存条出现了问题 电脑中病毒问题怎么处理 2 1如果是电脑中病毒 开机按电脑上的F8键 在电脑开机菜单栏找到 安全
  • 经典网络LeNet-5介绍及代码测试(Caffe, MNIST, C++)

    LeNet 5 包含7个层 layer 如下图所示 输入层没有计算在内 输入图像大小为32 32 1 是针对灰度图进行训练和预测的 论文名字为 Gradient Based Learning Applied to Document Reco
  • 为什么街头篮球总提示服务器维护,我玩街头篮球,但这几天它总是说连接不上服务器怎么回事?...

    我玩街头篮球 但这几天它总是说连接不上服务器怎么回事 來源 互聯網 2010 04 26 07 19 32 評論 分類 遊戲 gt gt 網絡遊戲 gt gt 街頭籃球 問題描述 我下载了补丁 參考答案 无法连接服务器 情况屡见不鲜 不巧
  • 如何应急响应

    应急响应事件分类 大致可以分为三类 1 勒索病毒 勒索病毒危害不言而喻 一旦中了勒索病毒 几乎很难破解 只能通过重装系统 数据备份恢复或者缴纳相应被勒索的比特币支付进行病毒解除 仍有一种比较渺茫的方式进行病毒解除 那就是溯源到攻击者 通过法
  • Expanding Low-Density Latent Regions for Open-Set Object Detection

    Expanding Low Density Latent Regions for Open Set Object Detection CVPR2022 Code https github com csuhan opendet2 这篇文章认为
  • 【Spring八】Spring与Hibernate整合

    Hibernate所需元素 三要素 实体类 hbm xml hibernate cfg xml Spring所需元素 applicationContext xml hibernate在操作数据库时 使用sessionFactory open
  • 华为OD机试 - 绘图机器(Java)

    题目描述 绘图机器的绘图笔初始位置在原点 0 0 机器启动后按照以下规则来进行绘制直线 1 尝试沿着横线坐标正向绘制直线直到给定的终点E 2 期间可以通过指令在纵坐标轴方向进行偏移 offsetY为正数表示正向偏移 为负数表示负向偏移 给定
  • 第一章 指针仪表识别之仪表检测

    文章目录 一 基于Hough变换的仪表检测 附源码 二 基于SURF模板匹配仪表检测 附源码 三 基于YOLO深度学习的仪表检测 附源码 指针式仪表读数算法主要用于工业变电站环境 变电站环境复杂 仪表类型众多 仪表图像通过巡检机器人的可见光
  • jdk17.0.6的安装配置

    下载资源 官网下载 Java Archive Downloads Java SE 17 oracle com https www oracle com java technologies javase jdk17 archive downl
  • Cuda Streams的概述(一)-- Cuda介绍

    最近在做有关Cuda的一个项目 碰到匪夷所思的问题 在异步的时候发现并没有达到预期的效果 程序没有异步起来 然后在网上找了一个Nvida的有关Cuda Streams的一个ppt 然后照着里面的提示 使程序达到了异步的效果 首先 先回顾一下
  • linux VLAN配置(vconfig)

    1 安装vlan vconfig 和加载8021q模块 aptitude install vlan modprobe 8021q 或 yum install vconfig modprobe 8021q lsmod grep i 8021q
  • AndroidStudio编译构建报错 Task ‘wrapper‘ not found in project ‘:xxx‘

    在项目 app 中找不到的任务 包装器 Task wrapper not found in project xxx 的问题 原因 build gradle 文件没有包装器任务 解决步骤 将此代码添加到 build gradle task w
  • PO、VO、DAO、BO、DTO、POJO 能分清吗?

    一 PO persistant object 持久对象 可以看成是与数据库中的表相映射的java对象 使用Hibernate来生成PO是不错的选择 二 VO value object 值对象 通常用于业务层之间的数据传递 和PO一样也是仅仅
  • vue中的h函数与JSX语法

    vue不仅像react一样实现了jsx 而且还借助jsx发挥了javascript动态画的优势 了解学习jsx可以让你更灵活的开发需求 一 h函数 在聊vue中的JSX之前 需要简单介绍一下 h 函数 理解了 h 函数 会更好的理解JSX