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。
相关推荐
mayaairi1 小时前
Vue2 事件绑定完全指南:从入门到原理
前端·javascript·vue.js
ℋᙚᵐⁱᒻᵉ鲸落7 小时前
移动端滑动手势冲突:overflow: auto导致外层横向滑动失效
前端·javascript·css·vue.js·html
用户500937683903913 小时前
热敏小票 Web 打印:我在 58/80mm 上折腾的两周
前端·vue.js
snow@li1 天前
服务器运维:Alibaba Cloud Linux 4 LTS・Vue前端 Java 后端 K3S 部署 CICD 目录规范清单
linux·前端·vue.js
honkun61 天前
vue 表格组件 vxe-table 实实现专业记账凭证编辑表格与自动汇总
前端·javascript·vue.js
web打印社区1 天前
网页静默打印热敏小票:从 HTML 到出纸的完整指南
前端·javascript·vue.js·electron·pdf·html
parade岁月2 天前
为了给表格加虚拟滚动而选了 vxe-table?也可以考虑下这个
前端·vue.js
鹏多多2 天前
PC 网站接入微信登录,这 10 个坑我替你踩完了!
前端·javascript·vue.js
染指11102 天前
103.RAG-LLamaIndex后端rag问答-聊天接口
前端·javascript·vue.js·人工智能
单线程_012 天前
从案例分析 Vue3 Tokenizer+Parser 源码三
前端·javascript·vue.js