学习笔记--Vue3 全套保姆级教程(附案例)

1 阅读7分钟

前言

本教程基于Vue3 + Vite(目前企业主流技术栈),覆盖 Vue3 全部核心功能、进阶特性、工程化用法,全程搭配可直接复制运行的实战案例,无跳过、无省略、无废话,零基础可学,资深开发者可查漏补缺。

教程特点:功能大纲系统化 + 知识点精讲 + 代码实战 + 场景说明 + 避坑指南,真正做到学完即用。

运行环境:Node.js 16+、VSCode、Vue3 单文件组件(SFC)

一、Vue3 完整功能大纲(系统化目录)

1. 基础核心

  • Vue 简介、搭建项目、模板语法

  • 插值、指令、修饰符

  • 响应式基础(ref/reactive)

  • 计算属性、侦听器

  • 样式绑定、Class绑定

  • 条件渲染、列表渲染

  • 事件处理、表单双向绑定

2. 组件基础

  • 组件注册、父子组件通信

  • Props 校验、默认值

  • 组件事件 emit

  • 插槽(默认插槽、具名插槽、作用域插槽)

  • 组件生命周期

3. 组合式API(Vue3核心)

  • setup 语法糖、执行时机

  • ref / reactive / toRefs / toRef

  • computed 计算属性

  • watch / watchEffect 侦听

  • 生命周期组合式API(onMounted/onUpdated等)

  • provide / inject 跨层通信

  • mitt 全局事件总线

  • 自定义hooks封装

4. 高阶进阶特性

  • 响应式原理精讲

  • Teleport 瞬移组件

  • Suspense 异步加载组件

  • KeepAlive 组件缓存

  • 动态组件、异步组件

  • 自定义指令

  • nextTick 异步更新队列

5. Vue工程化配套

  • Vue Router 路由(基础+高阶)

  • Pinia 状态管理

  • Vite 工程配置、环境变量

  • 组件封装、项目规范

二、环境搭建(保姆级第一步)

1. 创建Vue3项目(Vite)

打开终端,依次执行命令:

# 创建项目
npm create vite@latest vue3-demo -- --template vue

# 进入项目
cd vue3-demo

# 安装依赖
npm install

# 启动项目
npm run dev

启动成功后,访问http://localhost:5173 即可运行所有案例。后续所有代码均替换 src/App.vue 直接运行。

三、Vue3 基础核心(带实战案例)

1. 模板语法与插值

核心作用:在HTML中嵌入Vue变量、表达式,实现数据动态渲染。

规则:插值仅支持单行简单表达式,不支持语句、复杂逻辑。

实战案例:基础插值渲染

<template>
  <div class="demo">
    <!-- 基础变量插值 -->
    <p>用户名:{{ username }}</p>
    <!-- 表达式运算 -->
    <p>年龄+5:{{ age + 5 }}</p>
    <!-- 三元表达式 -->
    <p>状态:{{ isVip ? '会员' : '普通用户' }}</p>
    <!-- 方法调用 -->
    <p>拼接内容:{{ getText() }}</p>
  </div>
</template>

<script setup>
// 定义响应式变量
const username = "Vue工程师";
const age = 25;
const isVip = true;

// 定义方法
const getText = () => {
  return "顶级" + username;
};
</script>

2. 核心指令大全(常用全覆盖)

2.1 v-text / v-html

v-text:纯文本渲染,覆盖标签内容;v-html:解析HTML标签渲染(注意防XSS攻击)。

<template>
  <p v-text="text"></p>
  <p v-html="htmlStr"></p>
</template>

<script setup>
const text = "纯文本内容";
const htmlStr = "<span style='color:red'>红色HTML文本</span>";
</script>

2.2 v-bind 属性绑定(简写 :)

动态绑定HTML属性(class、style、src、title等),是最常用指令之一。

<template>
  <!-- 完整写法 -->
  <img v-bind:src="imgUrl" alt="">
  <!-- 简写写法(企业主流) -->
  <a :href="link">跳转链接</a>
  <div :title="tip">鼠标悬浮提示</div>
</template>

<script setup>
const imgUrl = "https://picsum.photos/200/200";
const link = "https://cn.vuejs.org/";
const tip = "Vue3官方文档";
</script>

2.3 v-on 事件绑定(简写 @)

绑定点击、输入、键盘等事件,支持传参、事件对象、修饰符。

<template>
  <!-- 无参事件 -->
  <button @click="handleClick">点击按钮</button>
  <!-- 传参事件 -->
  <button @click="handleParams(100, 'Vue')">传参点击</button>
  <!-- 获取事件对象 -->
  <button @click="handleEvent($event)">获取事件对象</button>
  <!-- 常用修饰符:prevent阻止默认行为 -->
  <a @click.prevent="handleLink" href="https://www.baidu.com">阻止跳转</a>
</template>

<script setup>
// 无参方法
const handleClick = () => {
  alert("按钮被点击了");
};

// 带参方法
const handleParams = (num, str) => {
  alert(`参数:${num}${str}`);
};

// 获取事件对象
const handleEvent = (e) => {
  console.log("事件对象:", e.target);
};

// 阻止默认行为
const handleLink = () => {
  alert("已阻止链接跳转");
};
</script>

2.4 v-model 双向绑定

表单核心指令,实现数据驱动视图、视图更新数据双向同步,支持所有表单元素。

<template>
  <!-- 输入框双向绑定 -->
  <input v-model="inputValue" placeholder="请输入内容">
  <p>实时输入内容:{{ inputValue }}</p>

  <!-- 单选框 -->
  <input type="radio" v-model="gender" value="男">男
  <input type="radio" v-model="gender" value="女">女
  <p>选中性别:{{ gender }}</p>

  <!-- 复选框 -->
  <input type="checkbox" v-model="hobby" value="编程">编程
  <input type="checkbox" v-model="hobby" value="阅读">阅读
  <p>选中爱好:{{ hobby }}</p>
</template>

<script setup>
    // 双向绑定变量
    const inputValue = "";
    const gender = "男";
    const hobby = [];
</script>

2.5 条件渲染 v-if / v-show

v-if:惰性渲染,条件为false时销毁DOM,适合切换频率低场景; v-show:通过CSS隐藏显示,DOM始终存在,适合频繁切换场景。

<template>
  <div>
    <h3>v-if 条件渲染</h3>
    <p v-if="score >= 90">优秀</p>
    <p v-else-if="score >= 60">及格</p>
    <p v-else>不及格</p>

    <h3>v-show 切换显示</h3>
    <p v-show="isShow">我是可切换显示的内容</p>
    <button @click="isShow = !isShow">切换显示隐藏</button>
  </div>
</template>

<script setup>
const score = 85;
let isShow = true;
</script>

2.6 列表渲染 v-for

遍历数组、对象,渲染列表,key必须唯一(推荐用id,不推荐用index)。

<template>
  <div>
    <h3>数组列表渲染</h3>
    <ul>
      <li v-for="(item, index) in list" :key="item.id">
        {{ index + 1 }} - {{ item.name }} - {{ item.age }}岁
      </li>
    </ul>

    <h3>对象遍历渲染</h3>
    <ul>
      <li v-for="(value, key) in userInfo" :key="key">
        {{ key }}:{{ value }}
      </li>
    </ul>
  </div>
</template>

<script setup>
// 数组数据
const list = [
  { id: 1, name: "张三", age: 20 },
  { id: 2, name: "李四", age: 22 },
  { id: 3, name: "王五", age: 24 }
];

// 对象数据
const userInfo = {
  姓名: "Vue工程师",
  岗位: "前端开发",
  工龄: "3年"
};
</script>

3. Vue3 响应式核心(ref / reactive)

Vue3响应式是核心特性,实现数据变、视图自动更新,两种API分工明确。

  • ref:适配基本数据类型(字符串、数字、布尔),也可适配对象,取值需要 .value

  • reactive:仅适配引用数据类型(对象、数组),无需 .value

实战案例:响应式数据更新

<template>
  <div>
    <p>ref数值:{{ num }}</p>
    <p>reactive用户姓名:{{ user.name }}</p>
    <button @click="updateData">更新响应式数据</button>
  </div>
</template>

<script setup>
// ref 定义基本类型响应式
import { ref, reactive } from 'vue';
const num = ref(10);

// reactive 定义对象响应式
const user = reactive({
  name: "小明",
  age: 20
});

// 修改数据方法
const updateData = () => {
  // ref修改必须加 .value
  num.value = 99;
  // reactive直接修改属性
  user.name = "Vue顶级工程师";
};
</script>

避坑指南:script-setup中,模板使用ref变量无需写.value,仅JS逻辑中需要。

4. 计算属性 computed

核心作用:基于现有数据派生新数据,自带缓存,依赖不变则不重复计算,适合复杂逻辑计算。

实战案例:购物车价格计算

<template>
  <div>
    <p>单价:{{ price }}元</p>
    <p>数量:{{ count }}件</p>
    <p>总价(计算属性):{{ totalPrice }}元</p>
    <button @click="count++">数量+1</button>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue';

const price = ref(99);
const count = ref(1);

// 只读计算属性
const totalPrice = computed(() => {
  console.log("计算执行了");
  return price.value * count.value;
});
</script>

核心优势:多次渲染页面,只要price、count不变,控制台只会打印一次,性能远优于直接写表达式

5. 侦听器 watch / watchEffect

用于监听数据变化,执行异步操作、复杂逻辑(接口请求、数据持久化等)。

5.1 watch 精准监听

<template>
  <input v-model="keyword" placeholder="输入关键词监听变化">
</template>

<script setup>
import { ref, watch } from 'vue';
const keyword = ref("");

// 监听单个数据
watch(keyword, (newVal, oldVal) => {
  console.log("新值:", newVal, "旧值:", oldVal);
  // 可在这里做搜索防抖、接口请求
}, { immediate: true }); // immediate: 初始加载立即执行
</script>

5.2 watchEffect 自动依赖收集

无需指定监听对象,自动收集内部依赖,依赖变化自动执行,代码更简洁。

<script setup>
import { ref, watchEffect } from 'vue';
const id = ref(1);

watchEffect(() => {
  // 自动监听id变化
  console.log("当前ID:", id.value);
  // 模拟接口请求
  // axios.get(`/api/list?id=${id.value}`)
});
</script>

四、组件核心实战(企业高频用法)

1. 父子组件通信 Props + Emit

组件通信是Vue开发核心,父传子用Props,子传父用emit自定义事件。

步骤1:创建子组件 src/components/Child.vue

<template>
  <div class="child">
    <p>子组件接收父组件数据:{{ msg }}</p>
    <button @click="sendMsg">子组件向父组件传值</button>
  </div>
</template>

<script setup>
// 1. 接收父组件参数 + 类型校验 + 默认值
const props = defineProps({
  msg: {
    type: String,
    default: "默认消息",
    required: true
  }
});

// 2. 定义自定义事件
const emit = defineEmits(['child-event']);

// 子组件触发事件
const sendMsg = () => {
  emit("child-event", "我是子组件传递的内容");
};
</script>

步骤2:父组件 App.vue 使用

<template>
  <div class="parent">
    <h3>父组件</h3>
    <Child :msg="parentMsg" @child-event="getChildData" />
    <p>接收子组件数据:{{ childData }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import Child from './components/Child.vue';

// 父组件数据
const parentMsg = ref("父组件专属消息");
const childData = ref("");

// 接收子组件传值
const getChildData = (val) => {
  childData.value = val;
};
</script>

2. 插槽全解析(默认/具名/作用域插槽)

插槽实现组件内容自定义,是封装通用组件的核心。

2.1 默认插槽

子组件预留位置,父组件传入任意内容。

<!-- 子组件 SlotDemo.vue -->
<template>
  <div class="box">
    <p>组件固定头部</p>
    <slot>默认占位内容</slot>
    <p>组件固定底部</p>
  </div>
</template>

<!-- 父组件使用 -->
<SlotDemo>
  <p>父组件自定义插入的内容</p>
</SlotDemo>

2.2 具名插槽

多个插槽精准匹配,实现多区域自定义。

<!-- 子组件 -->
<template>
  <slot name="header"></slot>
  <slot></slot>
  <slot name="footer"></slot>
</template>

<!-- 父组件使用 -->
<SlotDemo>
  <template #header>
    <h3>自定义头部</h3>
  </template>
  <p>默认主体内容</p>
  <template #footer>
    <p>自定义底部</p>
  </template>
</SlotDemo>

2.3 作用域插槽(高级)

子组件数据传给父组件,父组件自定义渲染格式,表格、列表封装必备。

<!-- 子组件 -->
<template>
  <ul>
    <li v-for="item in list" :key="item.id">
      <slot :row="item">{{ item.name }}</slot>
    </li>
  </ul>
</template>

<script setup>
const list = [
  { id: 1, name: "Vue", desc: "前端框架" },
  { id: 2, name: "Vite", desc: "构建工具" }
];
</script>

<!-- 父组件使用 -->
<ScopeSlot>
  <template #default="scope">
    <strong>{{ scope.row.name }}:{{ scope.row.desc }}</strong>
  </template>
</ScopeSlot>

3. 组件生命周期(组合式API)

生命周期是组件从创建、挂载、更新、销毁的全过程,用于处理组件不同阶段逻辑。

实战案例:生命周期执行顺序

<script setup>
import { 
  onBeforeMount, onMounted, 
  onBeforeUpdate, onUpdated,
  onBeforeUnmount, onUnmounted
} from 'vue';

// 挂载前
onBeforeMount(() => console.log("挂载前"));
// 挂载完成(接口请求、DOM操作首选)
onMounted(() => console.log("挂载完成"));
// 更新前
onBeforeUpdate(() => console.log("更新前"));
// 更新完成
onUpdated(() => console.log("更新完成"));
// 销毁前
onBeforeUnmount(() => console.log("销毁前"));
// 销毁完成(清除定时器、监听)
onUnmounted(() => console.log("销毁完成"));
</script>

核心场景:onMounted 页面加载请求接口,onUnmounted 清除定时器、事件监听,防止内存泄漏。

五、Vue3 高阶核心特性

1. 跨层通信 provide / inject

解决多层父子组件嵌套传值繁琐问题,祖先组件注入数据,任意后代组件直接获取。

实战案例:祖孙组件跨层传值

<!-- 顶层父组件 -->
<script setup>
import { provide, ref } from 'vue';
import GrandSon from './components/GrandSon.vue';

// 提供数据
const theme = ref("深色主题");
provide("theme", theme);
</script>

<template>
  <GrandSon />
</template>

<!-- 深层孙子组件 -->
<script setup>
import { inject } from 'vue';
// 注入数据,第二个参数为默认值
const theme = inject("theme", "默认主题");
</script>

<template>
  <p>获取顶层主题:{{ theme }}</p>
</template>

2. KeepAlive 组件缓存

缓存组件实例,避免组件重复销毁重建,保留页面状态、提升性能,列表页、表单页常用。

<template>
  <!-- 缓存内部组件 -->
  <KeepAlive>
    <component :is="currentComponent"></component>
  </KeepAlive>
</template>

3. Teleport 瞬移组件

将组件DOM结构挂载到任意页面节点,不受父组件样式、层级限制,弹窗、模态框必备。

<template>
  <button @click="show = true">打开弹窗</button>
  <Teleport to="body">
    <div v-if="show" class="modal">
      <p>全局弹窗(挂载到body)</p>
      <button @click="show = false">关闭</button>
    </div>
  </Teleport>
</template>

<script setup>
import { ref } from 'vue';
const show = ref(false);
</script>

<style scoped>
.modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  padding: 20px;
  background: #fff;
  border: 1px solid #eee;
}
</style>

4. 自定义指令

封装通用DOM操作,全局复用,常用场景:按钮权限、自动聚焦、复制文本。

实战案例:自动聚焦指令

<template>
  <input v-focus placeholder="页面自动聚焦">
</template>

<script setup>
// 自定义局部指令 v-focus
const vFocus = {
  mounted(el) {
    // 挂载后自动聚焦
    el.focus();
  }
};
</script>

5. nextTick 异步更新队列

Vue更新DOM是异步的,修改数据后无法立即获取最新DOM,nextTick可在DOM更新完成后执行回调

<template>
  <p ref="domRef">{{ text }}</p>
  <button @click="changeText">修改文本</button>
</template>

<script setup>
import { ref, nextTick } from 'vue';
const text = ref("旧文本");
const domRef = ref(null);

const changeText = async () => {
  text.value = "新文本";
  // 此时DOM未更新,获取旧值
  console.log("更新前:", domRef.value.innerText);

  // 等待DOM更新完成
  await nextTick();
  // 获取最新DOM值
  console.log("更新后:", domRef.value.innerText);
};
</script>

六、自定义Hooks封装(企业工程化必备)

Hooks是Vue3核心工程化思想,复用逻辑、剥离业务、代码解耦,替代Vue2混入。

实战案例:封装通用倒计时Hook

新建 src/hooks/useCountDown.js

import { ref } from 'vue';

export function useCountDown(initTime = 60) {
  // 倒计时数值
  const count = ref(0);
  let timer = null;

  // 开始倒计时
  const start = () => {
    count.value = initTime;
    timer = setInterval(() => {
      count.value--;
      if (count.value <= 0) {
        clearInterval(timer);
      }
    }, 1000);
  };

  return { count, start };
}

组件中使用

<template>
  <button @click="start">
    {{ count ? `${count}秒后重新获取` : "获取验证码" }}
  </button>
</template>

<script setup>
// 引入自定义hook
import { useCountDown } from './hooks/useCountDown';
const { count, start } = useCountDown(60);
</script>

优势:逻辑完全复用,多个组件可直接调用,无需重复编写倒计时逻辑。