前言
不管你写 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。