学习 Vue 3 全家桶 - JSX

2023-05-17 16:58:29 浏览数 (2)

# h 函数

在 Vue 3 的项目开发中,template 是 Vue 3 默认的写法。虽然 template 长得很像 HTML,但 Vue 其实会把 template 解析为 render 函数,之后,组件运行的时候通过 render 函数去返回虚拟 DOM,可以在 Vue Devtools 中看到组件编译之后的结果。

除了 template 之外,在某些场景下,可以直接写 render 函数来实现组件。由于 render 函数可以直接返回虚拟 DOM,因而就不再需要 template。

使用 defineComponent 定义一个组件,组件内部配置了 props 和 setup。这里的 setup 函数返回值是一个函数,就是 render 函数。render 函数返回 h 函数的执行结果,h 函数的第一个参数就是标签名,可以很方便地使用字符串拼接的方式, src/components/Heading.jsx:

代码语言:javascript复制
import { defineComponent, h } from 'vue';

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

src/pages/about.vue 中使用:

代码语言:javascript复制
<template>
  <h2>
    <Heading :level="2">H2</Heading>
    <Heading :level="3">H3</Heading>
  </h2>
</template>

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

手写的 h 函数,可以处理动态性更高的场景。但是如果是复杂的场景,h 函数写起来就显得非常繁琐,需要自己把所有的属性都转变成对象。并且组件嵌套的时候,对象也会变得非常复杂。

# JSX

为了有更方便的方式去写 h 函数,可以用 JSX。JSX 来源自 React 框架。

代码语言:javascript复制
const element = <h1 id="app">Hello, JSX!</h1>

这种在 JavaScript 里面写 HTML 的语法,就叫做 JSX,算是对 JavaScript 语法的一个扩展。上面的代码直接在 JavaScript 环境中运行时,会报错。JSX 的本质就是下面代码的语法糖,h 函数内部也是调用 createVnode 来返回虚拟 DOM。

代码语言:javascript复制
const element = createVnode('h1',{id:"app"}, 'hello JSX');

在从 JSX 到 createVNode 函数的转化过程中,需要安装一个 JSX 插件。

代码语言:javascript复制
npm install @vitejs/plugin-vue-jsx -D

vite.config.js 中配置:

代码语言:javascript复制
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue(), vueJsx()],
})

改用 JSX 代替 h 函数,就可以写出更加简洁的代码:

代码语言:javascript复制
import { defineComponent, h } from 'vue';

export default defineComponent({
  props: {
    level: {
      type: Number,
      required: true,
    },
  },
  setup(props, { slots }) {
    const HeadTag = `h${props.level}`;
    return () => <HeadTag>{slots.default()}</HeadTag>;
  }
});

使用 JSX 的本质,还是在写 JavaScript。在 Element3 组件库设计中,有很多组件需要用到 JSX,比如时间轴 Timeline、分页 Pagination、表格 Table 等等。

# JSX 和 Template

template 的语法是固定的,只有 v-if、v-for 等等语法。

JSX 只是 h 函数的一个语法糖,本质就是 JavaScript,想实现条件渲染可以用 if else,也可以用三元表达式,还可以用任意合法的 JavaScript 语法。也就是说,JSX 可以支持更动态的需求。而 template 则因为语法限制原因,不能够像 JSX 那样可以支持更动态的需求。这是 JSX 相比于 template 的一个优势。

JSX 相比于 template 还有一个优势,是可以在一个文件内返回多个组件,类似于返回多个函数一样。

实现业务需求的时候,优先使用 template,动态性要求较高的组件使用 JSX 实现,尽可能地利用 Vue 本身的性能优化。

template 由于语法固定,可以在编译层面做的优化较多,比如静态标记就真正做到了按需更新;而 JSX 由于动态性太强,只能在有限的场景下做优化,虽然性能不如 template 好,但在某些动态性要求较高的场景下,JSX 成了标配,这也是诸多组件库会使用 JSX 的主要原因。

0 人点赞