vue中的h函数与JSX语法

news2024/11/23 17:06:24

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实现

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

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

相关文章

[附源码]计算机毕业设计基于Springboot作业管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

WebLogic JVM Core dumps文件的生成控制

一&#xff0c;背景 当我们运行的WebLogic JVM发生Fatal Error时&#xff0c;会造成JVM crash掉&#xff0c;进而造成进程终止。一般来说crash的时间我们是无法估计在什么时候的&#xff0c;它具有很大的偶然性&#xff0c;因此理论上有时我们希望自动产生Core dump文件来提供…

figma有哪些快速入门的好用技巧

使用Figma在创建设计系统或处理大型设计项目时&#xff0c;总会涉及批量修改.快速定位.自动布局问题&#xff0c;MarcAndrew这篇文章分享了技巧&#xff0c;可以大大提高设计效率&#xff0c;希望对大家有所帮助: 在这篇文章中&#xff0c;我列出了一些快速简单的方法来帮助你…

YoLo V3 SPP u模型的讲解与总结

一。mosaic图像增强 其实就是将多张图片给汇总到一起&#xff0c;在源码当中就是默认使用4张图片进行拼接&#xff0c;进行预测。 优点&#xff1a; 增加数据的多样性增加目标个数BN能一次性统计多张图片的参数&#xff08;变相的增加了&#xff0c;输入一张图片其实就已经包…

Java agent 使用详解

一、前言 于一个即将上线的应用来说&#xff0c;系统监控是必不可少的&#xff0c;为什么需要监控呢&#xff1f;应用是跑在服务器上的&#xff0c;应用在运行过程中会发生各自意想不到的问题&#xff0c;像大家熟知的OOM&#xff0c;mysql故障&#xff0c;服务器宕机&#xff…

Mac docker-desktop 安装单机版k8s

文章目录01 引言02 下载安装docker desktop03 安装k8s04 安装k8s控制台&#xff08;k8s dashboard&#xff09;05 更方遍的方式安装dashboard01 引言 本文主要讲解在Mac下使用docker-desktop来安装k8s。 02 下载安装docker desktop 下载地址&#xff1a;https://www.docker.…

实例方法定义语法(四)

那么什么是方法呢&#xff1f; Java方法是语句的集合&#xff0c;它们在一起执行一个功能。 方法是解决一类问题的步骤的有序组合 方法包含于类或对象中 方法在程序中被创建&#xff0c;在其他地方被引用 1.方法的定义 类的方法定义类的某种行为或者功能。 方法定义的语法…

Allegro如何设置丝印位号优先显示操作指导

Allegro如何设置丝印位号优先显示操作指导 Allegro支持让丝印位号优先显示,可以让视图更加的清晰明了,按照需要的方式显示,具体操作如下 以下图为例 丝印位号被器件的外形盖住了,需要显示的效果为,优先显示丝印位号,器件外形次优先 选择display-layer Priority 出现Di…

MySQL日志系统

MySQL相关文章 慢sql搜集分析工具搭建 前言 日志系统可谓是MySQL中的重中之重&#xff0c;一些MySQL的特性也通过依赖于日志实现的。 本篇文章过一遍日志相关的东西&#xff0c;方便日后复习。 binlog 概念 二进制日志文件&#xff0c;记录了所有的DDL&#xff08;数据库…

tensorflow.keras常用模块介绍

目录前言一、基础层1-0、Input层1-1、Dense层1-2、Activation层&#xff08;激活层&#xff09;、Dropout层1-3、Lambda层1-4、Flatten层二、嵌入层2-1、Embedding层三、池化层3-1、MaxPooling1D层3-2、MaxPooling2D层3-3、AveragePooling1D层3-4、AveragePooling2D层3-5、Glob…

Android 组件化架构设计从原理到实战

为什么需要组件化 小项目是不需要组件化的。当一个项目有数十个人开发&#xff0c;编译项目要花费10分钟&#xff0c;修改一个bug就可能会影响到其他业务&#xff0c;小小的改动就需要进行回归测试&#xff0c;如果是这种项目&#xff0c;那么我们需要进行组件化了 组件化和模…

有效的渗透测试才能确保Web应用安全

应用程序的安全性和快速交付之间存在矛盾&#xff0c;但由于应用程序代码缺陷和安全漏洞&#xff0c;我们正在目睹或经历越来越多的攻击。据调查&#xff0c;软件安全漏洞占了大约47%的安全事故。 与任何软件一样&#xff0c;Web应用程序也包含缺陷和错误。这种安全风险的一个…

[附源码]Python计算机毕业设计Django物品捎带系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

SAP PS 第9节 合并采购申请、组合WBS之详解

SAP PS 第9节 合并采购申请、组合WBS之影响1 合并采购申请1.1 合并采购申请后台配置1.2 合并采购申请效果如下2 组合WBS2.1 后台配置2.1.1 激活需要分组的MRP组2.1.2 项目必须为有库存模式&#xff0c;无论估价或者未估价都可以2.1.3 物料必须允许项目库存&#xff08;允许独立…

Azkaban登录分析

分析意义:目前azkaban采用的是azkaban-users.xml配置文件的方式,配置登录用户。如果公司需要二次开发,增加安全性和便捷性,想从数据库取值呢,该如何着手开发呢?本文分析登录过程,便于进行azkaban的二次登录开发。 1、登录请求地址,请求方式和参数 请求地址:http://x…

mysql创建子账户

1.首先登陆root账户 [roothecs-219255 ~]# mysql -uroot -p首先在Xshell客户端登陆linux&#xff0c;然后输入mysql命令进行登陆。 2.创建子账户 创建一个用户名为test1&#xff0c;密码为123456的子账号&#xff0c;有两种方法&#xff0c;分别为&#xff1a; CREATE USER …

【多目标进化优化】NSGAII 算法原理与代码实现

前言 Gitee 代码地址&#xff1a;https://gitee.com/futurelqh/Multi-objective-evolutionary-optimization 理论分析 \quad\quadSrinivas 和 Deb 于 1993 年提出 了 NSGA (non-dominated sorting in genetic algorithm) (Srinivas et al, 1994)。NSGA 主要有三个方面的不足&…

Docker:数据卷(Data Volumes)dockerfile

目录 一、宿主机与容器之间的文件拷贝 从容器中拷贝文件到宿主机 从宿主机拷贝文件到容器 二、数据卷 三、数据卷容器 四、Dockerfile 1、自定义centos&#xff0c;具备vim及ifconfig作用 2、自定义tomcat8 一、宿主机与容器之间的文件拷贝 备份我们已经装好的docker 等备…

隔离式DC/DC高压模块5V12V24V转50V110V250V300V380V600V1100V短路保护直流升压可调开关控制电源模块

特点 ● 效率高达 70%以上 ● 1*2英寸标准封装 ● 单电压输出 ● 价格低 ● 稳压输出 ● 工作温度: -40℃~85℃ ● 阻燃封装&#xff0c;满足UL94-V0 要求 ● 温度特性好 ● 可直接焊在PCB 上 应用 HRB W2~25W 系列模块电源是一种DC-DC升压变换器。该模块电源的输入电压分为&a…

Android databinding之数据单向与双向绑定详解与使用(三)

一、介绍 通过前面两篇文档&#xff0c;我们大概了解了databinding的工作方式&#xff0c;view的初始化&#xff0c;recycleview的使用。但是这些UI都离不开数据的填充&#xff0c;数据的修饰。 在说到数据绑定&#xff0c;好多开发者平时在工作中也经常听到databinding的数据…