Vue 3 模板语法速通:彻底理解 `:`、`@`、`#`、`v-if`、`v-for` 与 `v-model`

Vue 3 模板语法速通:彻底理解 :@#v-ifv-forv-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-ifv-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> 部分,代码的可读性会提升非常明显。

相关推荐
DsirNg2 天前
从 `@wheel.prevent.stop` 到事件捕获:一次讲清浏览器事件流与 Vue 事件修饰符
javascript·vue·事件修饰符·事件冒泡·dom 事件·事件捕获·wheel
DsirNg2 天前
基于拓扑排序的画布自动布局:用最长上游路径决定节点列级
vue·流程图·拓扑排序·状态管理·有向图·自动布局·最长路径
way_hj3 天前
Flask笔记(2)快速web项目
笔记·flask·vue·web
Sterting4 天前
初识Vue3与开发环境搭建
前端·vue
sugar__salt4 天前
跟着 Demo 学 Pinia:两种仓库写法 + 完整 TodoList 复现
前端·javascript·vue.js·前端框架·vue
弹简特4 天前
【Vue3速成】09-Element Plus 核心组件实战与原理解析
vue·element-plus
钛态5 天前
AI 辅助:前端框架反模式:过度封装、状态滥用与副作用失控
前端·vue·react·web
by__csdn5 天前
Vue vs React vs Angular:前端框架终极对决
前端·vue.js·react.js·前端框架·vue·react·angular
钛态5 天前
前端框架选型决策框架:React、Vue、Svelte、Solid 的 2026 年横评
前端·vue·react·web