跳转到内容

Vue3 快速入门

这一章的目标不是把 Vue3 文档重新讲一遍,而是把大学生最常用的入门路径整理出来:什么时候该用 ref,什么时候该用 reactive,以及 <script setup> 为什么比旧写法更推荐。学完这一章,你应该能独立写出课程展示页、作品集卡片、简单表单和基础列表交互。

  • 建立 Vue3 响应式直觉
  • 掌握 <script setup> 的基本写法
  • 能独立完成表单、列表和组件通信
  • 减少“数据改了但页面没更新”这类新手问题

如果你以前用过 Vue2,最常见的感受可能是:datamethodscomputed 写在一起很方便,但功能变复杂后,同一个功能的逻辑会被拆到好几个选项里。

Vue3 的 Composition API 改变的是“按功能组织代码”的方式。最小可感差异是这样的:

import { ref, computed } from 'vue'
const count = ref(0)
const double = computed(() => count.value * 2)
function increment() {
count.value += 1
}

当你把表单验证、接口请求、组件交互都写进同一个函数时,代码的可读性会比分散在多个选项里更好。

在真实项目里,我推荐直接使用 <script setup>,因为它少了很多样板代码,而且 TypeScript 支持更好。一个最小示例是:

<script setup lang="ts">
import { ref } from 'vue'
const message = ref('Hello mcourse.app')
</script>
<template>
<p class="text-lg">{{ message }}</p>
</template>

这种写法适合学生实验、课程作业、个人作品集,也适合继续扩展成更复杂的组件。学这一套语法,毕业后做前端实习也仍然通用。

ref 适合简单值,比如字符串、数字、布尔值;reactive 更适合对象或数组,尤其是多个字段会一起变化的时候。你不需要强行统一成某一种,更实用的做法是:

  • 单个基础值用 ref
  • 表单对象、列表数据、配置项用 reactive
  • 需要跨组件共享状态时,再考虑 Piniaprovide/inject

初学者最常见的问题,是把 ref(0) 当成普通变量去修改,或者对 reactive 包裹的对象直接赋值整个对象。记住:ref.valuereactive 保持对象引用稳定。

Vue3 最常用的两个基础能力,一个是 v-for,一个是 v-if。学生项目里最常见的需求是“渲染一个任务列表,并且根据完成状态显示不同样式”。最小可运行的写法是:

<script setup lang="ts">
import { ref } from 'vue'
const items = ref([
{ id: 1, text: '完成课程阅读', done: true },
{ id: 2, text: '提交实验报告', done: false },
])
</script>
<template>
<ul>
<li v-for="item in items" :key="item.id">
<span :style="{ textDecoration: item.done ? 'line-through' : 'none' }">
{{ item.text }}
</span>
</li>
</ul>
</template>

这种写法已经是很多学生作业和课程展示页的最小交互单元。

Vue3 里的事件绑定比传统 DOM 写法更直接:@click@input@submit 就能把用户行为和组件状态连起来。如果你要做课程作业里的表单,可以这样起步:

<script setup lang="ts">
import { ref } from 'vue'
const name = ref('')
</script>
<template>
<form @submit.prevent>
<input v-model="name" placeholder="输入你的名字" />
<p>你好,{{ name || '同学' }}</p>
</form>
</template>

v-model 是 Vue3 表单开发里最值得先掌握的语法糖,它能把输入框值和响应式变量双向同步。

当你把项目从单页面扩展成多组件时,最常见的问题是“父组件怎么传数据,子组件怎么回传事件”。最小可用模式是:

  • 父传子:props
  • 子传父:$emit
  • 更复杂状态:再补 Piniaprovide/inject

学生项目里,你不需要一开始就把状态管理全家桶学完,先把 props 和 emit 用顺,足够应付课程作业和课程设计。

如果你现在刚开始学 Vue3,最不容易卡壳的顺序是:

  1. 先学会 <script setup>ref
  2. 理解 computed 与响应式依赖
  3. 学会用 v-forv-if@click 做基础交互
  4. 再补 watchwatchEffect 和组件通信

这个顺序不是最“全”的,但最能在最短时间内产出可运行的小页面。

如果你遇到“页面不更新”“绑定失效”“样式突然错位”,按这个顺序排查通常最快:

  1. 确认变量是不是 ref,有没有忘记 .value
  2. 检查 v-for 是否缺少 :key
  3. 看看是不是直接把新对象赋值给 reactive,导致引用断裂
  4. 确认事件名是不是写成了原生 DOM 写法,而不是 Vue 的 @click

很多新手问题其实不是“Vue 坏了”,而是响应式规则还没形成直觉。

进阶补充:生命周期与挂载时机

Section titled “进阶补充:生命周期与挂载时机”

Vue3 里,如果你需要在组件创建或挂载后执行一次逻辑,优先先理解这几个最小生命周期:

  • onMounted:组件已经挂载到页面上,适合发起请求或读取 DOM
  • onUnmounted:组件即将销毁,适合清理定时器或监听器
  • onUpdated:响应式数据变化导致视图更新后执行

学生项目里,最常见的误用是“一上来就想在组件外部直接操作 DOM”。先记住:涉及页面元素,优先在组件内部处理。

computed 不是“缓存变量”,它的核心价值是“声明派生状态”。适合用在:

  • 根据列表筛选结果计算统计值
  • 根据表单输入动态生成摘要
  • 根据多个状态组合出是否可提交

不适合用在:

  • 会主动修改状态的计算逻辑
  • 依赖异步副作用的场景

如果你发现自己写了一个“会改其他值”的计算属性,通常说明这里应该用函数,而不是 computed

watch 适合监听某个响应式变量的变化,并执行副作用,例如接口请求或路由跳转。最小可用的写法是:

watch(name, (newVal, oldVal) => {
console.log('名字从', oldVal, '变成', newVal)
})

不建议把所有逻辑都写进 watch。很多学生为了“数据变了自动处理”,把大量逻辑塞进侦听器,导致调用链不可解释。更好的原则是:

  • 派生状态优先用 computed
  • 用户行为优先用事件处理
  • 只有副作用才放进 watch

不是“一开始就要拆分组件”,而是“同一段逻辑或 UI 在第二处出现时,就该考虑拆了”。常见适合拆分的信号:

  • 多个页面出现相同卡片结构
  • 表单校验逻辑越来越长
  • 父子之间开始频繁传事件

拆分时不要求“一次做到完美”,只要让组件职责变清晰,后续扩展会容易很多。

进阶补充:样式隔离与作用域理解

Section titled “进阶补充:样式隔离与作用域理解”

Vue3 默认不会像某些框架那样自动样式隔离。如果你发现类名冲突,优先从这几个方向解决:

  • 给组件容器增加更具体的前缀类名
  • 用 BEM 或模块化思路组织类名
  • 必要时再用 CSS Modules 或 Scoped CSS

学生项目里,最常见的样式问题不是“不会隔离”,而是“组件结构太扁平,导致类名重复”。

进阶补充:从单页到路由的最小扩展

Section titled “进阶补充:从单页到路由的最小扩展”

当你开始做多页面作品集或课程展示站时,最先接触的通常是路由。Vue Router 的最小理解是:

  • 路径和组件对应关系
  • 动态参数如何传给页面
  • 前进后退如何保持状态

如果你现在只是做课程实验,可以先不用上手路由;但如果你想做出“可点进去、可分享链接”的小站,路由就是最值得补的一步。

课程项目里,最常见的动态需求就是从接口获取数据。学生最容易忽略的是加载态和错误态,一个最小可用的请求结构是:

  • 定义 dataloadingerror 三个状态
  • 请求开始前设置 loading = true
  • 请求结束后设置结果或错误
  • 在模板里用 v-if 分别渲染加载中、结果和错误

能做到这一点,你的页面就已经具备生产级交互的基本骨架。

<InteractiveQuiz title=“Vue3 小测” questions={[ { question: ‘Vue3 默认推荐用于组合式 API 的语法是?’, options: [‘Options API’, '