【Vue】认识单文件组件与模板语法

目录

      • [1. `<script setup>` ------ 逻辑的"自动暴露"入口](#1. <script setup> —— 逻辑的“自动暴露”入口)
      • [2. `<style scoped>` ------ 样式的"局部隔离罩"](#2. <style scoped> —— 样式的“局部隔离罩”)
      • [3. 多根节点 ------ 模板不再需要"一个根"](#3. 多根节点 —— 模板不再需要“一个根”)
      • [4. `v-bind`(简写 `:`) ------ 动态绑定 HTML 属性](#4. v-bind(简写 :) —— 动态绑定 HTML 属性)
      • [5. `v-on`(简写 `@`)+ 修饰符 ------ 事件绑定与便捷操作](#5. v-on(简写 @)+ 修饰符 —— 事件绑定与便捷操作)
      • 总结
      • 练习:点击按钮改变文字颜色或字体大小

单文件组件(Single-File Component,简称 SFC)就是以一个 .vue 文件结尾的文件。这个文件把 HTML、JavaScript、CSS 三个部分写在一起,用来描述一个独立的、可复用的 UI 部件(比如一个按钮、一张卡片、一个输入框,甚至整个页面)。

一个Vue单文件组件的标准结构如下:

Vue 复制代码
<template>
  <!-- 放 HTML 结构 -->
</template>

<script setup>
  // 放 JavaScript 逻辑(数据、函数等)
</script>

<style scoped>
  /* 放 CSS 样式 */
</style>

接下来,我们逐一拆解这三个部分以及相关的核心语法。


1. <script setup> ------ 逻辑的"自动暴露"入口

它是做什么的?

<script setup> 是 Vue 3 中一种更简洁的写法,用来写组件的 JavaScript 逻辑。你可以在里面定义 变量、函数、导入其他组件或工具 。重点在于:所有定义在顶层的东西,都会自动被 <template> 使用 ,不需要像 Vue 2 那样手动 return

有什么用?

让你写代码更简单、更直观。例如,你想在页面上显示一段文字,并绑定一个点击事件,可以这样写:

vue 复制代码
<template>
  <h1>{{ message }}</h1>
  <button @click="showAlert">点我</button>
</template>

<script setup>
// 普通变量(非响应式,适合静态展示)
const message = '你好,Vue 3!'

// 普通函数
function showAlert() {
  alert('按钮被点击了')
}
</script>

这里要说明,{{ }} 是 Vue 模板中的 插值语法。它的作用是把 JavaScript 表达式的值直接显示到页面上。

注意 :如果后续需要让 message 随用户操作而变化(比如点击按钮后改变文字),就需要用到 refreactive。现在我们主要使用它来定义普通变量和函数,用于简单的静态展示或事件触发。


2. <style scoped> ------ 样式的"局部隔离罩"

它是做什么的?

<style> 标签加上 scoped 属性,表示这个样式 只对当前组件的模板生效 ,不会影响到其他组件。Vue 在编译时会自动给当前组件的 HTML 元素添加一个唯一的属性(比如 data-v-7ba5bd90),然后重写你的 CSS 选择器,使其只匹配带有该属性的元素。

有什么用?

防止样式冲突。在一个大项目中,很可能多个组件里都有类名 .title.box,如果不加 scoped,后面引入的样式会覆盖前面的,导致样式错乱。使用 scoped 后,每个组件的样式都是独立的,互不干扰。

示例:

vue 复制代码
<!-- 组件 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 复制代码
<!-- Vue 2 写法 -->
<template>
  <div>
    <h1>标题</h1>
    <p>描述文字</p>
    <button>按钮</button>
  </div>
</template>

现在 Vue 3 可以这样:

vue 复制代码
<!-- Vue 3 写法 -->
<template>
  <h1>标题</h1>
  <p>描述文字</p>
  <button>按钮</button>
</template>

注意 :多根节点在某些边界情况下会有一些小问题(比如父组件向子组件传递 classstyle 时,不知道应该加到哪个根节点上)。但现在我们暂时不需要纠结这些,只需知道 Vue 3 支持多根节点即可。


以上三个知识点(<script setup><style scoped>、多根节点)构成了 .vue 文件的基本骨架。接下来,我们要学习在模板中动态控制元素的属性和行为。

4. v-bind(简写 :) ------ 动态绑定 HTML 属性

它是做什么的?

把 Vue 的数据(变量、表达式)绑定到 HTML 标签的属性 上。常见的属性包括:srchrefclassstyledisabledalt 等。普通情况下,这些属性是写死的(比如 <img src="/logo.png">),但使用 v-bind 后,属性值可以动态变化。

有什么用?

让页面可以根据数据状态自动调整元素的样式或行为。比如:

  • 根据条件给某个按钮添加 disabled 属性。
  • 根据图片 ID 动态生成图片 URL。
  • 根据某个布尔值切换 CSS 类名。

基本用法:

vue 复制代码
<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 函数。

有什么用?

实现用户交互。比如按钮点击后提交表单、输入框按下回车后搜索、鼠标移入时显示提示等。

基本用法:

vue 复制代码
<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

组合使用示例:

vue 复制代码
<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 表示同时阻止冒泡和默认行为。


总结

  1. 我们先学习了 .vue 文件的三个组成部分:逻辑<script setup>)、样式<style scoped>)、模板(支持多根节点)。
  2. 在模板中,为了让页面"活"起来,我们需要根据数据动态控制 HTML 属性 → 使用 v-bind:
  3. 同时,还需要响应用户的操作(点击、键盘等)→ 使用 v-on@ 绑定事件,并用修饰符简化常见操作。
  4. 至此,我们已经能够写出一个具有基本交互能力的 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 中运行):

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就是单位,如果不加上浏览器就识别不出来。

相关推荐
AIFQuant1 小时前
贵金属投资 APP 开发:实时报价、图表、提醒与交易数据全链路
开发语言·前端·websocket·金融·web app
爱吃羊的老虎1 小时前
【JAVA】python转java:Spring Boot 如何处理 Web 请求
java·前端·spring boot·http
shuoshuohaohao1 小时前
《JavaScript》
开发语言·前端·javascript
步步为营DotNet1 小时前
洞悉.NET 11:ASP.NET Core 10 在构建实时协作 Web 应用的技术实践
前端·asp.net·.net
Bigger1 小时前
mini-cc 的技能系统:给 AI 装上“专业外挂”
前端·ai编程·claude
繁星星繁1 小时前
LangChain 初探:模型调用、链式编排与运行机制
前端·chrome·langchain
z200509301 小时前
【linux学习】Linux 软硬链接深度解析:从 inode 到目录硬链接的那些坑
前端·chrome
编程猪猪侠2 小时前
基于uni-app-x 与 uni-app 的安卓与 H5 双向通信完整实现
android·javascript·uni-app