目录
- 1. `<script setup>` —— 逻辑的“自动暴露”入口
- 2. `<style scoped>` —— 样式的“局部隔离罩”
- 3. 多根节点 —— 模板不再需要“一个根”
- 4. `v-bind`(简写 `:`) —— 动态绑定 HTML 属性
- 5. `v-on`(简写 `@`)+ 修饰符 —— 事件绑定与便捷操作
- 总结
- 练习:点击按钮改变文字颜色或字体大小
单文件组件(Single-File Component,简称 SFC)就是以一个 .vue 文件结尾的文件。这个文件把 HTML、JavaScript、CSS 三个部分写在一起,用来描述一个独立的、可复用的 UI 部件(比如一个按钮、一张卡片、一个输入框,甚至整个页面)。
一个Vue单文件组件的标准结构如下:
<template> <!-- 放 HTML 结构 --> </template> <script setup> // 放 JavaScript 逻辑(数据、函数等) </script> <style scoped> /* 放 CSS 样式 */ </style>接下来,我们逐一拆解这三个部分以及相关的核心语法。
1.<script setup>—— 逻辑的“自动暴露”入口
它是做什么的?<script setup>是 Vue 3 中一种更简洁的写法,用来写组件的 JavaScript 逻辑。你可以在里面定义变量、函数、导入其他组件或工具。重点在于:所有定义在顶层的东西,都会自动被<template>使用,不需要像 Vue 2 那样手动return。
有什么用?
让你写代码更简单、更直观。例如,你想在页面上显示一段文字,并绑定一个点击事件,可以这样写:
<template> <h1>{{ message }}</h1> <button @click="showAlert">点我</button> </template> <script setup> // 普通变量(非响应式,适合静态展示) const message = '你好,Vue 3!' // 普通函数 function showAlert() { alert('按钮被点击了') } </script>这里要说明,{{ }} 是 Vue 模板中的 插值语法。它的作用是把 JavaScript 表达式的值直接显示到页面上。
注意:如果后续需要让message随用户操作而变化(比如点击按钮后改变文字),就需要用到ref或reactive。现在我们主要使用它来定义普通变量和函数,用于简单的静态展示或事件触发。
2.<style scoped>—— 样式的“局部隔离罩”
它是做什么的?
给<style>标签加上scoped属性,表示这个样式只对当前组件的模板生效,不会影响到其他组件。Vue 在编译时会自动给当前组件的 HTML 元素添加一个唯一的属性(比如data-v-7ba5bd90),然后重写你的 CSS 选择器,使其只匹配带有该属性的元素。
有什么用?
防止样式冲突。在一个大项目中,很可能多个组件里都有类名.title或.box,如果不加scoped,后面引入的样式会覆盖前面的,导致样式错乱。使用scoped后,每个组件的样式都是独立的,互不干扰。
示例:
<!-- 组件 A --> <template> <div class="box">组件 A 的盒子</div> </template> <style scoped> .box { background-color: red; } </style> <!-- 组件 B --> <template> <div class="box">组件 B 的盒子</div> </template> <style scoped> .box { background-color: blue; } </style>渲染后,组件 A 的盒子背景是红色,组件 B 的盒子背景是蓝色,互不影响。
注意:如果需要让父组件的样式影响子组件内部的元素(比如想统一设置所有按钮的样式),可以用:deep()选择器,但这属于进阶用法,先了解scoped的作用即可。
3. 多根节点 —— 模板不再需要“一个根”
它是做什么的?
在 Vue 2 中,每个组件的<template>里必须有一个唯一的根元素(通常用一个<div>包裹所有内容)。Vue 3 移除了这个限制,你可以直接写多个并列的顶层元素。
有什么用?
减少不必要的包裹元素,让生成的 HTML 结构更干净。例如,一个组件要输出一个标题 + 一段描述 + 一个按钮,以前必须这样:
<!-- Vue 2 写法 --> <template> <div> <h1>标题</h1> <p>描述文字</p> <button>按钮</button> </div> </template>现在 Vue 3 可以这样:
<!-- Vue 3 写法 --> <template> <h1>标题</h1> <p>描述文字</p> <button>按钮</button> </template>注意:多根节点在某些边界情况下会有一些小问题(比如父组件向子组件传递class或style时,不知道应该加到哪个根节点上)。但现在我们暂时不需要纠结这些,只需知道 Vue 3 支持多根节点即可。
以上三个知识点(<script setup>、<style scoped>、多根节点)构成了.vue文件的基本骨架。接下来,我们要学习在模板中动态控制元素的属性和行为。
4.v-bind(简写:) —— 动态绑定 HTML 属性
它是做什么的?
把 Vue 的数据(变量、表达式)绑定到 HTML 标签的属性上。常见的属性包括:src、href、class、style、disabled、alt等。普通情况下,这些属性是写死的(比如<img src="/logo.png">),但使用v-bind后,属性值可以动态变化。
有什么用?
让页面可以根据数据状态自动调整元素的样式或行为。比如:
- 根据条件给某个按钮添加
disabled属性。 - 根据图片 ID 动态生成图片 URL。
- 根据某个布尔值切换 CSS 类名。
基本用法:
<template> <!-- 绑定图片地址 --> <img :src="imageUrl" alt="动态图片"> <!-- 绑定 disabled 属性 --> <button :disabled="isDisabled">提交</button> <!-- 绑定 class(对象语法:键是类名,值是布尔值) --> <div :class="{ active: isActive, 'text-bold': isBold }">动态类</div> <!-- 绑定 class(数组语法) --> <div :class="['base', isActive ? 'active' : '']">数组方式</div> <!-- 绑定 style(对象语法) --> <div :style="{ color: textColor, fontSize: fontSize + 'px' }">动态样式</div> </template> <script setup> const imageUrl = 'https://picsum.photos/200/150' const isDisabled = true const isActive = true const isBold = false const textColor = 'red' const fontSize = 20 </script>注意:v-bind:可以简写为:,这是最常用的写法。另外,class 和 style 的增强写法在实际开发中使用频率极高,一定要熟练。
: 的本质是:把属性从“静态字符串”变成“动态响应式绑定”,让属性值能够跟随数据变化。这就是它与普通 HTML 写法的根本区别。
也就是会把属性等号后面的引号里的内容被当作 JavaScript 代码来执行,而不是纯文本。
5.v-on(简写@)+ 修饰符 —— 事件绑定与便捷操作
它是做什么的?
监听 DOM 事件(如点击、键盘输入、鼠标移动等),在事件发生时执行指定的 JavaScript 函数。
有什么用?
实现用户交互。比如按钮点击后提交表单、输入框按下回车后搜索、鼠标移入时显示提示等。
基本用法:
<template> <button @click="handleClick">点我</button> </template> <script setup> function handleClick(event) { console.log('点击了', event.target) } </script>事件修饰符:这是 Vue 提供的一组便捷语法,用来处理常见的事件细节,例如阻止冒泡、阻止默认行为、只在特定按键时触发等。它们以.加后缀的形式写在事件名后面。
| 修饰符 | 作用 | 示例 |
|---|---|---|
.stop | 阻止事件冒泡(不再触发父元素的事件) | @click.stop |
.prevent | 阻止默认行为(如<form>提交刷新页面) | @submit.prevent |
.enter | 只在回车键触发(用于@keyup) | @keyup.enter |
.once | 事件只触发一次 | @click.once |
.self | 只有event.target是当前元素时才触发 | @click.self |
组合使用示例:
<template> <!-- 阻止冒泡 + 阻止默认行为 --> <form @submit.prevent.stop="onSubmit"> <input type="text" /> <button type="submit">提交(页面不刷新,且不冒泡)</button> </form> <!-- 按回车触发搜索 --> <input @keyup.enter="search" placeholder="输入后按回车" /> <!-- 只触发一次 --> <button @click.once="onceClick">仅生效一次</button> </template> <script setup> const onSubmit = () => console.log('表单提交了') const search = (e) => console.log('搜索:', e.target.value) const onceClick = () => alert('只能点出一次') </script>注意:修饰符可以串联,比如@click.stop.prevent表示同时阻止冒泡和默认行为。
总结
- 我们先学习了
.vue文件的三个组成部分:逻辑(<script setup>)、样式(<style scoped>)、模板(支持多根节点)。 - 在模板中,为了让页面“活”起来,我们需要根据数据动态控制 HTML 属性 → 使用
v-bind(:)。 - 同时,还需要响应用户的操作(点击、键盘等)→ 使用
v-on(@)绑定事件,并用修饰符简化常见操作。 - 至此,我们已经能够写出一个具有基本交互能力的 Vue 组件了。
练习:点击按钮改变文字颜色或字体大小
要求:
创建一个 Vue 组件,包含一段文字和几个按钮。点击按钮可以改变文字的颜色或字体大小。
提示:
- 颜色和字体大小是动态变化的数据,需要使用
ref来定义(这是阶段2的知识点,但请先按下面的方式照做,后续会系统学习)。 - 在
<script setup>中:import { ref } from 'vue',然后用const textColor = ref('red')定义响应式数据,修改时用textColor.value = 'blue',模板中直接写textColor(不带.value)。 - 字体大小同理:
const fontSize = ref(16),修改时fontSize.value += 4。
完整代码(可直接复制到src/App.vue中运行):
<template> <div> <!-- 动态绑定颜色和字体大小 --> <p :style="{ color: textColor, fontSize: fontSize + 'px' }" class="demo-text"> 这是一段可变化的文字 </p> <div class="button-group"> <button @click="textColor = 'red'">红色</button> <button @click="textColor = 'green'">绿色</button> <button @click="textColor = 'blue'">蓝色</button> <button @click="fontSize += 2">放大字体</button> <button @click="fontSize -= 2">缩小字体</button> <button @click="reset">重置</button> </div> </div> </template> <script setup> import { ref } from 'vue' const textColor = ref('black') const fontSize = ref(16) function reset() { textColor.value = 'black' fontSize.value = 16 } </script> <style scoped> .demo-text { transition: all 0.2s; margin-bottom: 16px; padding: 8px; border: 1px solid #ddd; border-radius: 6px; } .button-group button { margin-right: 8px; margin-bottom: 8px; padding: 6px 12px; cursor: pointer; } </style>第一句代码中,:style加上的是内联样式,除非加上!important,它的优先级就是最高的。还有px就是单位,如果不加上浏览器就识别不出来。