Vue 3 模板语法速通:彻底理解 :、@、#、v-if、v-for 与 v-model
在学习 Vue 3 时,我们经常会看到一些看起来不像普通 HTML 的代码:
vue
<img :src="avatar" />
<button @click="submit">
提交
</button>
<div v-if="visible">
Hello Vue
</div>
<li
v-for="item in list"
:key="item.id"
>
{{ item.name }}
</li>
<input v-model="username" />
<template #footer>
底部内容
</template>
第一次接触 Vue 时,很容易产生一个疑问:
text
:
@
#
v-if
v-for
v-model
{{ }}
这些东西到底是什么?
实际上,它们都属于 Vue 最核心的一套规则:
Vue 模板语法(Template Syntax)
Vue 模板语法的作用,可以简单理解成:
把 HTML 和 JavaScript 数据连接起来。
普通 HTML 本身基本是静态的,而 Vue 允许我们在 HTML 中使用变量、判断、循环、事件等 JavaScript 逻辑。
一、什么是 Vue 模板?
一个典型的 Vue 3 单文件组件可能是:
vue
<template>
<div>
<h1>{{ title }}</h1>
<button @click="changeTitle">
修改标题
</button>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const title = ref('Hello Vue')
function changeTitle() {
title.value = 'Vue 3'
}
</script>
其中:
vue
<template>
里面就是 Vue 的模板。
可以暂时把它理解成:
text
HTML
+
Vue 模板语法
例如普通 HTML:
html
<h1>Hello</h1>
Vue 可以写:
vue
<h1>{{ title }}</h1>
这里的:
vue
{{ title }}
就已经不是普通 HTML,而是 Vue 模板语法了。
二、Vue 模板语法解决什么问题?
假设 JavaScript 中存在:
ts
const username = 'Tom'
我们希望网页显示:
text
欢迎 Tom
如果是普通 JavaScript,可能需要:
js
document.querySelector('#username').innerText = username
Vue 不需要我们手动寻找 DOM。
直接写:
vue
<p>欢迎 {{ username }}</p>
当:
ts
username
发生变化时,页面也会自动更新。
因此 Vue 一个非常重要的思想就是:
text
数据
↓
模板
↓
页面
而不是不断:
text
查找 DOM
修改 DOM
查找 DOM
修改 DOM
三、最基础的模板语法:{``{ }}
Vue 最容易理解的模板语法就是:
vue
{{ }}
它通常叫:
Mustache 插值语法 / 文本插值
例如:
vue
<script setup lang="ts">
const username = 'Tom'
</script>
<template>
<h1>Hello {{ username }}</h1>
</template>
最终页面显示:
text
Hello Tom
四、{``{ }} 里面不仅可以写变量
很多初学者容易认为:
vue
{{ }}
里面只能放变量。
实际上,它可以放 JavaScript 表达式。
例如:
vue
{{ count + 1 }}
vue
{{ username.toUpperCase() }}
vue
{{ isLogin ? '已登录' : '未登录' }}
vue
{{ user.name }}
例如:
vue
<script setup lang="ts">
const price = 10
const count = 5
</script>
<template>
<p>总价:{{ price * count }}</p>
</template>
结果:
text
总价:50
所以可以把:
vue
{{ }}
理解成:
在 HTML 文本位置执行一个 JavaScript 表达式,并把结果显示出来。
五、为什么 HTML 属性不能直接使用 {``{ }}?
假设有:
ts
const avatar = '/images/avatar.png'
很多初学者可能会尝试:
vue
<img src="{{ avatar }}" />
这是错误的。
Vue 中:
vue
{{ }}
主要用于:
HTML 标签之间的文本内容。
例如:
vue
<p>{{ username }}</p>
而 HTML Attribute 想绑定 JavaScript 数据,需要使用:
text
v-bind
也就是我们经常看到的:
text
:
六、最重要的符号之一:冒号 :
例如:
vue
<img :src="avatar" />
这里的:
text
:
实际上是:
text
v-bind:
的缩写。
所以:
vue
<img :src="avatar" />
完整写法是:
vue
<img v-bind:src="avatar" />
两者完全等价。
七、没有 : 和有 : 有什么区别?
这是理解 Vue 模板语法非常关键的一步。
1. 没有冒号
vue
<img src="avatar" />
这里:
text
avatar
就是普通字符串。
相当于告诉浏览器:
text
图片地址就是 "avatar"
浏览器可能真的会寻找:
text
/avatar
这个资源。
2. 有冒号
vue
<img :src="avatar" />
现在 Vue 会认为:
text
avatar 不是字符串
avatar 是 JavaScript 表达式
假设:
ts
const avatar = '/images/user.png'
那么:
vue
<img :src="avatar" />
最终效果相当于:
html
<img src="/images/user.png" />
八、理解 : 的最好方法
可以记住一句话:
没有
:,引号里面通常是字符串;有:,引号里面是 JavaScript。
例如:
vue
<div class="active"></div>
这里:
text
active
是字符串。
但是:
vue
<div :class="activeClass"></div>
这里:
text
activeClass
是 JavaScript 变量。
再例如:
vue
<button disabled="false">
这里的:
text
false
甚至仍然是 HTML 属性字符串。
而 Vue 中可以:
vue
<button :disabled="false">
这里的:
ts
false
才是真正的 JavaScript Boolean。
九、:class 是 Vue 中非常常见的写法
Vue 经常需要动态修改 CSS class。
例如:
vue
<script setup lang="ts">
const active = true
</script>
<template>
<div :class="{ active: active }">
Hello
</div>
</template>
意思是:
text
如果 active === true
就添加 class="active"
还可以简写为:
vue
<div :class="{ active }">
Vue 项目中经常看到这样的代码:
vue
<section
:class="[
'app-main',
{
'fullscreen-app-main': isFullScreenAppMain
}
]"
>
这是什么意思?
拆开来看:
vue
'app-main'
永远存在。
而:
vue
'fullscreen-app-main'
只有:
ts
isFullScreenAppMain === true
时才会添加。
所以它最终可能是:
html
<section class="app-main">
或者:
html
<section class="app-main fullscreen-app-main">
这就是 Vue 的动态 Class。
十、:style:动态控制 CSS
除了:
vue
:class
还经常使用:
vue
:style
例如:
vue
<script setup lang="ts">
const fontSize = 24
</script>
<template>
<div :style="{ fontSize: fontSize + 'px' }">
Hello Vue
</div>
</template>
最终可能产生:
html
<div style="font-size: 24px">
十一、Vue 指令到底是什么?
前面看到的:
vue
v-bind
属于 Vue 的:
Directive ------ 指令
Vue 指令通常以:
text
v-
开头。
例如:
text
v-bind
v-on
v-if
v-else
v-show
v-for
v-model
v-slot
这些指令告诉 Vue:
这个 HTML 元素需要执行某种特殊的 Vue 行为。
十二、Vue 指令的基本结构
一个比较完整的 Vue 指令可能长这样:
vue
v-on:click.stop
可以拆成:
text
v-on
│
│ 指令
│
└──── :click
│
│ 参数
│
└──── .stop
│
└── 修饰符
也就是:
text
指令 : 参数 . 修饰符
例如:
vue
v-on:click.stop
含义:
text
v-on
→ 监听事件
click
→ 监听 click 事件
stop
→ 阻止事件继续冒泡
这套结构理解以后,很多 Vue 语法就不神秘了。
十三、@:事件绑定
Vue 中第二个极其常见的符号就是:
text
@
例如:
vue
<button @click="submit">
提交
</button>
这里:
text
@
其实也是缩写。
完整写法:
vue
<button v-on:click="submit">
简写:
vue
<button @click="submit">
所以:
text
@
=
v-on:
十四、@click
例如:
vue
<script setup lang="ts">
function submit() {
console.log('提交')
}
</script>
<template>
<button @click="submit">
提交
</button>
</template>
当用户点击按钮时:
ts
submit()
就会被调用。
整个过程可以理解成:
text
用户点击按钮
↓
@click
↓
调用 submit()
↓
执行 JavaScript
十五、常见的事件
Vue 可以监听绝大多数浏览器 DOM 事件。
例如:
vue
@click="handleClick"
点击。
vue
@input="handleInput"
输入。
vue
@change="handleChange"
值发生确认性的改变。
vue
@focus="handleFocus"
获得焦点。
vue
@blur="handleBlur"
失去焦点。
vue
@keydown="handleKeydown"
键盘按下。
vue
@submit="handleSubmit"
表单提交。
十六、事件修饰符
Vue 对事件提供了一套非常方便的修饰符。
例如:
vue
@click.stop="handleClick"
这里:
text
.stop
表示阻止事件冒泡。
类似于 JavaScript:
js
event.stopPropagation()
再例如:
vue
<form @submit.prevent="submit">
这里:
text
.prevent
表示:
js
event.preventDefault()
阻止表单默认提交行为。
常见修饰符包括:
text
.stop
.prevent
.self
.once
.capture
十七、键盘修饰符
Vue 还可以非常方便地监听某些键。
例如:
vue
<input @keyup.enter="submit" />
意思是:
text
用户松开 Enter 键
↓
调用 submit()
因此不需要自己写:
js
if (event.key === 'Enter') {
submit()
}
常见的还有:
text
.enter
.tab
.delete
.esc
.space
.up
.down
.left
.right
十八、v-if:条件渲染
假设:
ts
const isLogin = true
可以:
vue
<div v-if="isLogin">
欢迎回来
</div>
意思是:
text
如果 isLogin === true
↓
创建这个 DOM
否则:
text
这个 DOM 不存在
十九、v-else
例如:
vue
<div v-if="isLogin">
欢迎回来
</div>
<div v-else>
请先登录
</div>
逻辑相当于:
ts
if (isLogin) {
// 欢迎回来
} else {
// 请先登录
}
二十、v-else-if
还可以:
vue
<div v-if="score >= 90">
优秀
</div>
<div v-else-if="score >= 60">
及格
</div>
<div v-else>
不及格
</div>
与 JavaScript:
ts
if (...) {
} else if (...) {
} else {
}
非常类似。
二十一、v-if 和 v-show 有什么区别?
这是非常常见的 Vue 面试题。
假设:
vue
<div v-if="visible">
Hello
</div>
当:
ts
visible = false
时:
DOM 元素会被移除。
而:
vue
<div v-show="visible">
Hello
</div>
当:
ts
visible = false
时,DOM 还存在,只是变成类似:
css
display: none;
所以可以简单理解:
text
v-if
→ 创建 / 删除 DOM
v-show
→ DOM 一直存在
→ 通过 CSS 隐藏
通常:
text
切换不频繁
→ v-if
频繁显示 / 隐藏
→ v-show
二十二、v-for:循环渲染
假设有:
ts
const users = [
{ id: 1, name: 'Tom' },
{ id: 2, name: 'Jack' },
{ id: 3, name: 'Lucy' }
]
我们希望生成三个:
html
<li>
可以:
vue
<li
v-for="user in users"
:key="user.id"
>
{{ user.name }}
</li>
相当于:
text
users
↓
循环
↓
Tom
Jack
Lucy
二十三、v-for 中的 index
还可以获得数组索引:
vue
<li
v-for="(user, index) in users"
:key="user.id"
>
{{ index }} - {{ user.name }}
</li>
结果可能是:
text
0 - Tom
1 - Jack
2 - Lucy
二十四、为什么 v-for 经常和 :key 一起出现?
例如:
vue
<li
v-for="user in users"
:key="user.id"
>
这里:
text
key
非常重要。
Vue 在更新列表时,需要知道:
text
这个 DOM 对应哪个数据?
所以:
vue
:key="user.id"
就像给每一个元素一个稳定的身份证。
例如:
text
user 1
→ key = 1
user 2
→ key = 2
user 3
→ key = 3
当数组顺序变化时,Vue 可以更加准确地复用和更新对应 DOM。
因此列表渲染时通常应该提供一个:
稳定、唯一的 key。
最理想的是:
vue
:key="item.id"
而不是随意使用:
vue
:key="index"
二十五、key 为什么前面有 :?
例如:
vue
:key="user.id"
因为:
text
user.id
是 JavaScript 表达式。
如果写:
vue
key="user.id"
那么所有元素得到的其实都是字符串:
text
"user.id"
而:
vue
:key="user.id"
Vue 才会真正读取:
ts
user.id
的值。
二十六、v-model:双向数据绑定
这是 Vue 最经典的功能之一。
例如:
vue
<script setup lang="ts">
import { ref } from 'vue'
const username = ref('')
</script>
<template>
<input v-model="username" />
<p>
你输入的是:{{ username }}
</p>
</template>
当用户输入:
text
Tom
以后:
ts
username.value
也会变成:
text
Tom
反过来,如果 JavaScript 修改:
ts
username.value = 'Jack'
输入框也会自动显示:
text
Jack
因此叫:
双向数据绑定。
二十七、如何理解 v-model?
可以画成:
text
用户输入
↓
<input>
↓
v-model
↓
username
↑
│
JavaScript 修改
也就是:
text
页面 → 数据
数据 → 页面
都可以同步。
二十八、v-model 常用于哪些元素?
常见包括:
vue
<input v-model="username" />
文本框。
vue
<textarea v-model="content"></textarea>
多行文本。
vue
<select v-model="city">
下拉框。
vue
<input
type="checkbox"
v-model="checked"
/>
复选框。
vue
<input
type="radio"
v-model="gender"
/>
单选框。
除此之外,Vue 组件也可以实现自己的 v-model。
二十九、#:插槽语法
Vue 中第三个经常出现的特殊符号是:
text
#
例如:
vue
<template #header>
标题
</template>
这个:
text
#
也是缩写。
完整写法:
vue
<template v-slot:header>
简写:
vue
<template #header>
因此:
text
#
=
v-slot:
三十、什么是 Slot?
可以把 Slot 理解成:
子组件提前留好的"插槽位置"。
例如一个 Card 组件内部:
vue
<template>
<div class="card">
<header>
<slot name="header" />
</header>
<main>
<slot />
</main>
<footer>
<slot name="footer" />
</footer>
</div>
</template>
父组件可以:
vue
<Card>
<template #header>
用户信息
</template>
<p>
Tom
</p>
<template #footer>
<button>
确定
</button>
</template>
</Card>
相当于告诉 Card:
text
#header
→ 放进 header
普通内容
→ 放进默认 slot
#footer
→ 放进 footer
Element Plus 等组件库中会大量使用 Slot。
三十一、Vue 三个重要缩写
到这里,可以先记住 Vue 最重要的三个特殊符号:
| 缩写 | 完整写法 | 作用 |
|---|---|---|
: |
v-bind: |
动态绑定数据 |
@ |
v-on: |
绑定事件 |
# |
v-slot: |
指定插槽 |
可以简单记成:
text
:
数据进来
@
事件出去
#
内容插进去
这是阅读 Vue 模板非常实用的一种记忆方法。
三十二、Vue 的特殊 Attribute:key
除了各种 Directive,Vue 本身还有一些特殊 Attribute。
例如:
text
key
ref
is
它们并不是普通业务属性,而是在 Vue 渲染机制中具有特殊意义。
首先来看:
text
key
例如:
vue
<component
:is="Component"
:key="route.path"
/>
其中:
vue
:key="route.path"
相当于告诉 Vue:
当前组件实例的身份由
route.path区分。
如果:
ts
route.path
发生改变,Vue 可以据此判断组件是否应当作为新的节点处理。
三十三、ref:获得 DOM 或组件引用
例如:
vue
<input ref="myInput" />
这里:
text
ref
相当于给这个 DOM 一个 Vue 层面的引用名称。
Vue 3 <script setup> 中经常配合模板引用使用。
例如:
vue
<script setup lang="ts">
import { ref, onMounted } from 'vue'
const myInput = ref<HTMLInputElement | null>(null)
onMounted(() => {
myInput.value?.focus()
})
</script>
<template>
<input ref="myInput" />
</template>
这样 JavaScript 就能够访问真正的:
html
<input>
DOM 节点。
因此可以把:
text
ref
理解成:
给 DOM 或组件建立一个可以从 JavaScript 访问的引用。
三十四、:is:动态组件
在 Vue 项目中经常会看到:
vue
<component :is="Component" />
这是非常重要的一种动态组件写法。
其中:
vue
<component>
是 Vue 提供的内置组件。
而:
vue
:is="Component"
表示:
当前到底渲染哪个组件,由
Component变量决定。
例如:
ts
const currentComponent = UserPanel
然后:
vue
<component :is="currentComponent" />
相当于动态渲染:
vue
<UserPanel />
如果变量改成:
ts
currentComponent = SettingsPanel
就会切换成:
vue
<SettingsPanel />
三十五、实际项目中的 :is
例如 Vue Router 中经常看到:
vue
<router-view v-slot="{ Component, route }">
<component
:is="Component"
:key="route.path"
/>
</router-view>
这里整个逻辑可以理解成:
text
router-view
↓
根据当前 URL 找到页面组件
↓
得到 Component
↓
<component :is="Component">
↓
真正渲染这个页面组件
所以:
vue
:is="Component"
的意思就是:
"我要渲染的具体组件不是写死的,而是由变量
Component决定。"
三十六、v-slot="{ Component, route }" 又是什么?
例如:
vue
<router-view v-slot="{ Component, route }">
这里使用的是:
text
v-slot
它接收 RouterView 提供的数据。
其中:
vue
{ Component, route }
又使用了 JavaScript 的:
对象解构。
可以简单理解成 RouterView 给了我们一个对象:
ts
{
Component: 当前页面组件,
route: 当前路由信息
}
然后:
vue
v-slot="{ Component, route }"
把其中两个成员拿出来使用。
三十七、v-if="!route.meta.link" 怎么读?
例如:
vue
<component
:is="Component"
v-if="!route.meta.link"
:key="route.path"
/>
这一行其实可以直接翻译成人话。
首先:
vue
:is="Component"
表示:
text
渲染 Component 对应的组件
然后:
vue
v-if="!route.meta.link"
表示:
text
只有 route.meta.link 不存在或者为 false 时才渲染
最后:
vue
:key="route.path"
表示:
text
使用当前路由路径作为组件的 key
整句话就是:
如果当前路由不是外链页面,那么渲染 RouterView 提供的 Component,并使用当前 route.path 作为组件身份标识。
三十八、:include="tagsViewStore.cachedViews" 怎么读?
再比如:
vue
<keep-alive :include="tagsViewStore.cachedViews">
这里还是我们前面说的:
text
:
=
v-bind:
所以完整写法:
vue
<keep-alive
v-bind:include="tagsViewStore.cachedViews"
>
意思就是:
将 JavaScript 中的
tagsViewStore.cachedViews动态传给 KeepAlive 的include。
如果没有冒号:
vue
include="tagsViewStore.cachedViews"
那就只是字符串:
text
"tagsViewStore.cachedViews"
完全不是一回事。
三十九、:enter-active-class="animate" 怎么读?
例如:
vue
<transition
:enter-active-class="animate"
>
还是一样的规则。
假设:
ts
const animate = 'animate__fadeIn'
那么:
vue
:enter-active-class="animate"
最终相当于:
text
enter-active-class
=
"animate__fadeIn"
这里没有出现任何新的 Vue 规则。
本质仍然只是:
text
v-bind
四十、动态参数
Vue 甚至允许:
text
属性名本身也是动态的
例如:
vue
<a :[attributeName]="url">
假设:
ts
attributeName = 'href'
那么相当于:
vue
<a :href="url">
如果:
ts
attributeName = 'title'
那么又相当于:
vue
<a :title="url">
这种语法叫:
动态参数。
四十一、事件也可以动态
例如:
vue
<button @[eventName]="handler">
假设:
ts
eventName = 'click'
相当于:
vue
<button @click="handler">
如果:
ts
eventName = 'dblclick'
则相当于:
vue
<button @dblclick="handler">
实际普通项目中不一定经常使用,但理解它有助于看懂 Vue 指令的设计方式。
四十二、v-text
Vue 还有一个:
text
v-text
例如:
vue
<p v-text="username"></p>
类似于:
vue
<p>{{ username }}</p>
一般情况下:
vue
{{ username }}
可读性更好,因此使用更多。
四十三、v-html
如果字符串本身包含 HTML:
ts
const content = '<strong>Hello</strong>'
普通:
vue
<div>{{ content }}</div>
会把 HTML 当成文本显示。
如果:
vue
<div v-html="content"></div>
Vue 会把它解析成 HTML。
页面显示:
text
Hello
并且是粗体。
不过:
text
v-html
必须非常谨慎。
不要直接渲染不可信的用户输入,否则可能产生 XSS 安全问题。
四十四、v-once
例如:
vue
<div v-once>
{{ username }}
</div>
表示:
这个区域只渲染一次。
之后:
ts
username
即使变化,这里的内容也不会继续更新。
普通业务中使用频率相对较低。
四十五、静态 Attribute 与动态 Attribute
学习 Vue 时,最好建立一个明确的分类。
静态 Attribute
vue
<div class="panel">
vue
<img src="/logo.png">
vue
<input type="text">
这里都是普通 HTML。
动态 Attribute
vue
<div :class="panelClass">
vue
<img :src="logo">
vue
<input :disabled="disabled">
这里:
text
:
告诉 Vue:
后面的值是 JavaScript 表达式。
四十六、HTML Attribute 和组件 Props
例如普通 HTML:
vue
<img :src="avatar">
这里:
text
src
属于 HTML Attribute。
但如果是自定义组件:
vue
<UserCard :user="currentUser" />
这里:
text
user
通常就是传给:
text
UserCard
组件的 Prop。
所以:
text
:
不仅可以绑定 HTML 属性:
vue
:src
:class
:style
:disabled
还大量用于:
父组件向子组件传递动态数据。
例如:
vue
<UserCard
:name="username"
:age="age"
:user="user"
/>
四十七、一个非常典型的 Vue 模板
现在来看一个完整例子:
vue
<script setup lang="ts">
import { ref, computed } from 'vue'
const username = ref('Tom')
const users = ref([
{ id: 1, name: 'Tom' },
{ id: 2, name: 'Jack' },
{ id: 3, name: 'Lucy' }
])
const showList = ref(true)
const userCount = computed(() => {
return users.value.length
})
function toggleList() {
showList.value = !showList.value
}
</script>
<template>
<div class="user-panel">
<h1>
用户管理系统
</h1>
<p>
当前用户:{{ username }}
</p>
<p>
用户数量:{{ userCount }}
</p>
<input v-model="username" />
<button @click="toggleList">
显示 / 隐藏
</button>
<ul v-if="showList">
<li
v-for="user in users"
:key="user.id"
>
{{ user.name }}
</li>
</ul>
</div>
</template>
如果已经理解前面的内容,现在应该可以从上往下直接阅读。
四十八、逐行翻译这个模板
首先:
vue
<p>
当前用户:{{ username }}
</p>
意思:
text
读取 username
并显示在页面
然后:
vue
<input v-model="username" />
意思:
text
输入框和 username 双向绑定
然后:
vue
<button @click="toggleList">
意思:
text
点击按钮
→ 调用 toggleList()
然后:
vue
<ul v-if="showList">
意思:
text
showList === true
才创建 ul
然后:
vue
v-for="user in users"
意思:
text
循环 users
然后:
vue
:key="user.id"
意思:
text
使用 user.id 作为当前列表节点的 key
最后:
vue
{{ user.name }}
意思:
text
显示当前用户的 name
这就是 Vue 模板的基本阅读方式。
四十九、Vue 模板语法其实只有几个核心思想
当我们把所有奇怪符号拆开以后,会发现 Vue Template 并没有想象中复杂。
核心实际上可以归纳为下面几类。
第一类:显示数据
vue
{{ data }}
例如:
vue
{{ username }}
第二类:绑定属性
vue
:属性="JavaScript表达式"
例如:
vue
:src="avatar"
vue
:class="className"
vue
:key="item.id"
vue
:is="Component"
第三类:监听事件
vue
@事件="函数"
例如:
vue
@click="submit"
vue
@change="change"
vue
@keyup.enter="search"
第四类:控制页面结构
vue
v-if
v-else-if
v-else
v-show
v-for
例如:
vue
<div v-if="visible">
或者:
vue
<div v-for="item in list">
第五类:表单绑定
vue
v-model
例如:
vue
<input v-model="username">
第六类:组件内容分发
vue
v-slot
也就是:
text
#
例如:
vue
<template #footer>
五十、Vue 模板符号速查表
最后可以把 Vue 中最常见的模板语法整理成这张表:
| 语法 | 作用 | 示例 |
|---|---|---|
{``{ }} |
文本插值 | {``{ username }} |
: |
v-bind: 缩写 |
:src="avatar" |
@ |
v-on: 缩写 |
@click="submit" |
# |
v-slot: 缩写 |
#footer |
v-if |
条件创建 DOM | v-if="visible" |
v-else-if |
条件分支 | v-else-if="..." |
v-else |
最终条件分支 | v-else |
v-show |
CSS 显示隐藏 | v-show="visible" |
v-for |
循环渲染 | v-for="item in list" |
v-model |
双向绑定 | v-model="username" |
v-text |
设置文本 | v-text="message" |
v-html |
渲染 HTML | v-html="content" |
v-once |
只渲染一次 | v-once |
key |
节点身份标识 | :key="item.id" |
ref |
DOM / 组件引用 | ref="inputRef" |
is |
动态组件类型 | :is="Component" |
五十一、以后应该怎样阅读 Vue 模板?
以后看到一段复杂 Vue 代码,例如:
vue
<router-view v-slot="{ Component, route }">
<transition
:enter-active-class="animate"
mode="out-in"
>
<keep-alive
:include="tagsViewStore.cachedViews"
>
<component
:is="Component"
v-if="!route.meta.link"
:key="route.path"
/>
</keep-alive>
</transition>
</router-view>
不要把它当成一整块来看。
应该逐个识别 Vue 语法。
首先:
vue
v-slot="{ Component, route }"
表示:
text
接收 RouterView 提供的数据
然后:
vue
:enter-active-class="animate"
表示:
text
动态绑定 animate
然后:
vue
:include="tagsViewStore.cachedViews"
表示:
text
动态绑定缓存组件列表
然后:
vue
:is="Component"
表示:
text
动态决定当前渲染哪个组件
然后:
vue
v-if="!route.meta.link"
表示:
text
根据条件决定是否创建组件
最后:
vue
:key="route.path"
表示:
text
使用当前路由路径作为组件 key
这样一拆,原本看起来非常复杂的一段 Vue 代码,本质上不过是在组合几条已经掌握的模板规则。
五十二、总结
Vue 模板语法表面上有很多特殊符号:
text
{{ }}
:
@
#
v-if
v-for
v-model
:key
:is
ref
但这些语法背后只有一个核心目的:
让 HTML 能够使用 JavaScript 中的数据和逻辑。
最需要优先记住的是:
text
{{ }}
→ 把数据显示出来
:
→ 把 JavaScript 数据绑定给属性或组件
@
→ 监听事件
v-if
→ 判断
v-for
→ 循环
v-model
→ 表单双向绑定
#
→ 插槽
如果再进一步压缩,可以记成:
text
HTML 负责页面结构
JavaScript 负责数据和逻辑
Vue 模板语法负责把两者连接起来
所以以后再看到:
vue
<component
:is="Component"
v-if="!route.meta.link"
:key="route.path"
/>
就不需要把它当成什么特殊的"Vue 黑魔法"。
它只是:
text
: → 动态绑定
v-if → 条件判断
:key → 给节点身份
:is → 决定渲染哪个组件
把这些基础规则掌握以后,再去阅读 Vue Router、Element Plus、Pinia 甚至大型 Vue 3 项目的 <template> 部分,代码的可读性会提升非常明显。