Vue 渲染体系“三件套”(template 模板语法、h 函数和 JSX 语法)

前言

不管你写 template、h() 还是 JSX,最后都会变成 VNode → patch → DOM

一、template 模板语法------ 最常用、最友好

特点:

  • 面向业务开发
  • 声明式
  • 会被编译成 render 函数

1、插值表达式

typescript 复制代码
<div>{{ message }}</div>

数据变化 → 自动更新 DOM

2、指令系统(Vue 模板核心)

指令 作用
v-bind 绑定属性
v-on 绑定事件
v-if / v-else 条件渲染
v-for 列表渲染
v-model 双向绑定
v-slot 插槽
typescript 复制代码
<button @click="add">+1</button>
<img :src="imgUrl" />
<li v-for="item in list" :key="item.id">{{ item.name }}</li>

3、组件 & 插槽

typescript 复制代码
<MyCard title="标题">
  <template #default>
    内容
  </template>
</MyCard>

本质:

  • 模板不会直接操作 DOM,而是被编译成:
typescript 复制代码
render() {
  return h('div', message)
}

4、简单示例

typescript 复制代码
<script setup>
import { ref } from 'vue'

const count = ref(0)
const add = () => count.value++
</script>

<template>
  <div class="box">
    <p>Count: {{ count }}</p>
    <button @click="add">+1</button>
  </div>
</template>

二、h() 函数------ 虚拟 DOM 的直接写法

特点:

  • render 函数的核心
  • 手写虚拟 DOM
  • 所有模板最终都会变成 h()

基本格式:

typescript 复制代码
h(type, props, children)

1、普通元素

typescript 复制代码
h('div', { class: 'box' }, 'Hello')

2、子节点数组

typescript 复制代码
h('ul', null, [
  h('li', null, 'A'),
  h('li', null, 'B')
])

3、事件绑定

typescript 复制代码
h('button', { onClick: this.add }, 'Add')

4、渲染组件

typescript 复制代码
h(MyCard, { title: '标题' }, {
  default: () => h('span', '内容')
})

本质:

  • h() 返回 VNode 对象
typescript 复制代码
{
  type: 'div',
  props: { class: 'box' },
  children: 'Hello'
}

然后进入:

typescript 复制代码
patch(oldVNode, newVNode)

5、简单示例

typescript 复制代码
import { h, ref } from 'vue'

export default {
  setup() {
    const count = ref(0)
    const add = () => count.value++

    return () =>
      h('div', { class: 'box' }, [
        h('p', null, 'Count: ' + count.value),
        h('button', { onClick: add }, '+1')
      ])
  }
}

三、JSX 语法------ 更自由的"类模板语法"

特点:

  • 本质是 h() 的语法糖
  • JS 表达能力更强
  • 适合复杂动态结构

1、JSX 写法

typescript 复制代码
return <div class="box">{msg}</div>

编译后:

typescript 复制代码
h('div', { class: 'box' }, msg)

2、条件渲染

typescript 复制代码
return count > 0
  ? <span>正数</span>
  : <span>负数</span>

3、列表渲染

typescript 复制代码
return (
  <ul>
    {list.map(item => <li key={item.id}>{item.name}</li>)}
  </ul>
)

4、插槽

typescript 复制代码
return <MyCard v-slots={{
  default: () => <span>内容</span>
}} />

5、简单示例

typescript 复制代码
import { ref } from 'vue'

export default {
  setup() {
    const count = ref(0)
    const add = () => count.value++

    return () => (
      <div class="box">
        <p>Count: {count.value}</p>
        <button onClick={add}>+1</button>
      </div>
    )
  }
}

四、三者关系总结

typescript 复制代码
Template  → 编译 → render 函数 → h()
JSX       → 编译 → h()
h()       → 生成 VNode
VNode     → patch → 真实 DOM

它们只是"写法不同",底层渲染机制完全一样。

  • Template 最好写,h() 最底层,JSX 最灵活;
  • 三者最终都会变成 h() 创建的 VNode,再由 Vue 的 patch 机制更新真实 DOM。
相关推荐
M ? A1 小时前
Vue3 转 React:组件透传 Attributes 与 useAttrs 使用详解|VuReact 实战
前端·javascript·vue.js·经验分享·react.js·开源·vureact
欧阳天风1 小时前
vue3的组件优化
前端·vue.js·性能优化
打瞌睡的朱尤1 小时前
蓝桥杯复习大纲
前端·javascript·vue.js
甄心爱学习2 小时前
【项目实训(个人3)】
vue.js·人工智能·python·个人开发
a1117762 小时前
三维地图可视化 ThreeJS vue 开源项目
前端·javascript·vue.js
布局呆星13 小时前
Vue3 | 组件通信学习小结
前端·vue.js
Ruihong16 小时前
你的 Vue 3 reactive(),VuReact 会编译成什么样的 React?
vue.js·面试
Ruihong16 小时前
你的 Vue 3 ref(),VuReact 会编译成什么样的 React?
vue.js·面试
一 乐16 小时前
酒店预订|基于springboot + vue酒店预订系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·酒店预订系统
嗜好ya17 小时前
解决 Vite 项目中 import.meta.env 变量为 undefined 的问题
前端·javascript·vue.js