插值、v-bind 与 v-on
模板语法与常用指令 · 阅读后完成下方实验与检查题,再用「标记完成」记录进度。
学习目标
这一节聚焦模板里最常写的三件事:把数据渲染成文本(插值)、把数据绑定到 HTML 属性(v-bind)、把用户操作绑定到方法(v-on)。学完你能把一个静态 HTML 页面改造成数据驱动的模板,并知道每个指令背后的简写和求值规则。
问题场景
产品给了你一张用户卡片的设计稿:头像、昵称、简介、关注按钮、外链主页。用原生 JS 写要 querySelector 一堆节点、手动 textContent 和 setAttribute;用模板语法,整张卡片应该只依赖一个数据对象,数据变则卡片变。但第一次写模板容易踩三个坑:属性里直接写 {{ }} 不生效、事件传参丢事件对象、动态属性名不知道怎么写。
核心解释
插值只用于文本内容:{{ expression }},表达式是任意 JS 表达式(三元、运算、函数调用都行),但只能是单个表达式,不能写 if 语句。插值渲染的是纯文本,HTML 标签会被转义——这是防 XSS 的默认行为。
<script setup>
const user = { name: "阿吉", bio: "写代码,也写周报", followers: 128 };
const isFollowing = false;
</script>
<template>
<article class="card">
<h2>{{ user.name }}</h2>
<p>{{ user.bio }}</p>
<p>关注者:{{ user.followers }} 人 · 状态:{{ isFollowing ? "已关注" : "未关注" }}</p>
</article>
</template>
v-bind 用于属性绑定。HTML 属性里不能写插值(href="{{ url }}" 是错的),必须用 v-bind:attr,简写是冒号:
<script setup>
const user = { homepage: "https://example.com", avatar: "/avatar.png" };
const activeClass = "is-active";
</script>
<template>
<a :href="user.homepage" :title="`${user.homepage} 的主页`">主页</a>
<img :src="user.avatar" alt="用户头像" :class="activeClass" />
</template>
class 和 style 有增强写法::class 可以接对象(键是类名,值是布尔)或数组;:style 可以接对象,属性名用驼峰或短横线都行:
class 与 style 有增强写法::class 可以接对象(键是类名,值是布尔)或数组,例如 :class="{ 'is-active': isFollowing }";:style 接对象,属性名用驼峰或短横线都行,例如 :style="{ color: isFollowing ? 'green' : '#666' }"。
v-on 绑定事件,简写 @。等号右边可以是方法引用、内联语句、或带参数的方法调用:
<script setup>
import { ref } from "vue";
const count = ref(0);
const lastEvent = ref("无");
function handleClick(event) {
count.value += 1;
lastEvent.value = event.type;
}
</script>
<template>
<button @click="handleClick">方法引用(自动收到事件对象)</button>
<button @click="count++">内联语句</button>
<button @click="(e) => handleClick(e)">内联箭头函数</button>
<p>点击次数:{{ count }} · 最近事件:{{ lastEvent }}</p>
</template>
规则很简单:写方法名(不带括号)时 Vue 自动把事件对象传进去;写调用 handleClick() 时事件对象不会自动传,需要显式写 $event。常用修饰符直接跟在事件后:@submit.prevent 阻止默认行为、@click.stop 阻止冒泡、@keyup.enter 只在回车时触发。
示例拆解
把用户卡片做成完整可运行版本,注意三处细节:
<script setup>
import { ref } from "vue";
const user = {
name: "阿吉",
bio: "写代码,也写周报",
followers: 128,
homepage: "https://example.com",
avatar: "https://placehold.co/64",
};
const isFollowing = ref(false);
function toggleFollow() {
isFollowing.value = !isFollowing.value;
user.followers += isFollowing.value ? 1 : -1;
}
</script>
<template>
<article class="card">
<img :src="user.avatar" :alt="`${user.name} 的头像`" width="64" height="64" />
<h2>{{ user.name }}</h2>
<p>{{ user.bio }}</p>
<a :href="user.homepage" target="_blank" rel="noreferrer">主页</a>
<p>关注者:{{ user.followers }}</p>
<button @click="toggleFollow">
{{ isFollowing ? "取消关注" : "关注" }}
</button>
</article>
</template>
细节一:user 是普通对象,user.followers += 1 不会触发更新——但这里 isFollowing 变了,组件本来就会重渲染,顺带读到新的 followers。这是「偶然正确」,不要依赖。要让 followers 也响应式,得用 reactive() 包一层,V03 讲。
细节二::alt 用了模板字符串,Vue 模板支持完整 JS 表达式,包括模板字符串和三元。
细节三:@click="toggleFollow" 不带括号,事件对象自动传入;函数里没用 event 也没关系。
动手任务
- 给卡片加一个「粉丝数格式化」:超过 1000 显示
1.2k,用插值里的三元或函数调用实现。 - 把主页链接改成「未提供主页时显示灰色不可点文本」,用
v-if(下一节内容,可先试)或三元绑定:href实现。 - 给关注按钮加
:disabled绑定:当user.homepage为空时禁用,并给禁用态加一个is-disabledclass。
常见错误
- 在属性里写插值:
<a href="{{ url }}">不会生效,浏览器会把{{ url }}当字面量。必须:href="url"。 :class传了字符串却期待对象行为::class="'is-active'"是静态字符串,布尔切换要传对象{ 'is-active': cond }。@click="handleClick()"想拿事件对象:括号调用不会自动传 event,要么去掉括号,要么写@click="handleClick($event)"。- 在模板里写语句:
{{ if (x) ... }}是语法错误。模板表达式只能是表达式,复杂逻辑抽成函数或computed。
检查与复盘
- 能说清插值、v-bind、v-on 各自解决什么问题,简写分别是什么
- 能写出
:class的对象语法和数组语法 - 能解释「方法引用」和「方法调用」在事件绑定上的差别
参考资料
- Vue 官方文档「模板语法」:插值、指令、动态参数的完整规则
- Vue 官方文档「Class 与 Style 绑定」:对象/数组语法的边界情况
- Vue 官方文档「事件处理」:修饰符与
$event的用法
读完这一课了?
标记完成后,工作台会安排接下来的学习。