跳到主要内容

1.2 第一个 Vue 组件

本章目标: 亲眼看到“修改状态 → 页面更新”的过程,理解一个 .vue 文件的三个部分。

写一个计数器​

把 vue-lab/src/App.vue 替换为:

src/App.vue
<script setup lang="ts">
import { ref } from 'vue';

const count = ref(0);

function increment() {
count.value++;
}

function reset() {
count.value = 0;
}
</script>

<template>
<main class="counter">
<h1>我的第一个 Vue 组件</h1>
<p>已点击 {{ count }} 次</p>
<button type="button" @click="increment">加一</button>
<button type="button" @click="reset">重置</button>
</main>
</template>

<style scoped>
.counter {
max-width: 36rem;
margin: 3rem auto;
padding: 1rem;
}
button {
margin-right: 0.75rem;
padding: 0.5rem 1rem;
}
</style>

运行 npm run dev,点击“加一”。数字应递增,点击“重置”应恢复为零。

初始样式

脚手架可能在 main.ts 引入演示用的全局 CSS。如果页面居中方式或颜色与你预期不同,可以移除该演示样式的导入,再观察这里的组件样式。

三个区域分别负责什么​

区域用途对照你的经验
<script setup lang="ts">声明状态、函数、导入组件UI 背后的代码逻辑
<template>描述状态如何显示类似 Razor 模板,但由 Vue 编译
<style scoped>编写当前组件的样式CSS 作用范围由编译器辅助限制

setup 中顶层声明可以直接用于模板,不需要手动返回。lang="ts" 开启 TypeScript 语法。scoped 不等于 Shadow DOM;它通过选择器标记限制大部分样式影响范围。

状态驱动视图​

ref(0) 返回一个 Vue 响应式引用。脚本里通过 .value 读取或修改;模板对顶层 ref 自动解包,所以写 {{ count }}。

一次点击的过程
点击按钮 → 执行 increment → 修改 count.value → Vue 更新对应文本

你不需要先找到 <p>,再手工修改 DOM。页面显示内容由状态推导。

普通变量不会自动刷新页面

let count = 0 能保存数字,但变量变化不会被 Vue 作为响应式依赖追踪。Vue 的 ref 也不是 C# 里的按引用传参关键字。

为什么事件写成 @click​

@click="increment" 是 v-on:click="increment" 的简写。Vue 在点击时执行函数,而不是在渲染模板时执行它。

{{ count }} 是文本插值,class="counter" 是普通 HTML 属性,@click 是 Vue 指令。下一阶段会先补齐理解这些表达式所需的前端基础。

练习​

增加一个“减一”按钮,并让计数不能小于零。验收:连续点击“减一”时页面最低显示零。

参考答案

在脚本中增加:

function decrement() {
count.value = Math.max(0, count.value - 1);
}

在模板中增加:

<button type="button" @click="decrement" :disabled="count === 0">
减一
</button>

函数保证数据规则,:disabled 表达按钮状态。两者结合,既保护逻辑也让用户看到当前限制。

下一步: HTML、CSS 与浏览器。参考:单文件组件。