前言

Vue.js 作为前端三大主流框架之一,以其「渐进式框架」的特性、简洁的 API 和优秀的易用性,成为前端开发者的首选技术栈。本学期围绕 Vue.js 展开了系统性学习,从基础语法、组件化开发,到 Vue 3 的 Composition API、Pinia 状态管理、工程化构建,再到企业级项目中的性能优化、跨端适配,形成了完整的技术闭环。本文将以「原理 + 实战 + 工程化」为核心,结合 10 + 实战场景、百余个可落地代码片段,深度解析 Vue.js 的核心知识点与企业级应用技巧,全文超 10000 字,力求覆盖从入门到进阶的全维度内容。

一、Vue.js 核心认知:从设计理念到生态体系

1.1 Vue.js 的核心特性与设计理念

Vue.js 的核心设计理念是「渐进式框架」(Progressive Framework),即开发者可以根据需求逐步引入 Vue 的功能模块,而非一次性引入全部特性。核心特性包括:

  • 数据驱动视图:基于 MVVM(Model-View-ViewModel)架构,通过数据绑定实现视图与数据的双向同步,无需手动操作 DOM;
  • 组件化开发:将页面拆分为独立、可复用的组件,降低代码耦合度,提升维护性;
  • 轻量级:核心库仅关注视图层,体积小(Vue 3 生产环境包约 10KB),且可与其他库 / 现有项目无缝集成;
  • 响应式系统:Vue 3 基于 Proxy 实现响应式,相比 Vue 2 的 Object.defineProperty,支持数组、新增属性的监听,且性能更优;
  • 指令系统:提供 v-if、v-for、v-bind、v-on 等指令,简化 DOM 操作;
  • 生态完善:配套 Vue Router(路由)、Pinia/Vuex(状态管理)、Vue Test Utils(测试)、Vite(构建工具)等生态工具。

1.2 Vue 生态体系全景

核心模块 功能定位 版本适配
Vue Core 核心库(响应式、组件、指令等) Vue 2 / Vue 3
Vue Router 路由管理,实现单页应用(SPA) Vue Router 3(Vue 2)/ Vue Router 4(Vue 3)
Pinia 新一代状态管理库,替代 Vuex Vue 3(推荐)
Vuex 传统状态管理库 Vue 2 / Vue 3(兼容)
Vite 极速构建工具,替代 Webpack Vue 3(推荐)
Vue CLI 脚手架工具 Vue 2 / Vue 3
Element Plus 企业级 UI 组件库 Vue 3
Element UI 企业级 UI 组件库 Vue 2
Vue Test Utils 单元测试工具 Vue 2 / Vue 3
Vue Devtools 调试工具 Vue 2 / Vue 3

1.3 Vue 2 vs Vue 3 核心差异

维度 Vue 2 Vue 3
核心架构 Options API(选项式 API) Composition API(组合式 API)+ Options API(兼容)
响应式原理 Object.defineProperty(仅支持对象属性监听) Proxy(支持对象、数组、新增属性监听)
性能 虚拟 DOM 重写前,性能一般 虚拟 DOM 重写,编译优化,性能提升 50%+
体积 约 20KB(生产版) 约 10KB(生产版,支持 Tree-Shaking)
类型支持 弱 TypeScript 支持 原生 TypeScript 支持,类型推断更完善
生命周期 beforeCreate/created 等 setup 替代 beforeCreate/created,其余生命周期前缀加 on(如 onMounted)
多根节点 不支持(必须有唯一根节点) 支持多根节点(Fragment)

二、Vue 3 基础核心:从语法到响应式原理

2.1 环境搭建:Vite+Vue 3 工程初始化

2.1.1 快速创建项目

bash

运行

# 初始化Vite+Vue 3项目(npm)
npm create vite@latest vue3-demo -- --template vue-ts
# 进入项目目录
cd vue3-demo
# 安装依赖
npm install
# 启动开发服务
npm run dev
2.1.2 工程结构解析(Vite+Vue 3+TS)

plaintext

vue3-demo/
├── node_modules/        // 依赖包
├── public/              // 静态资源(不参与打包,如favicon.ico)
├── src/
│   ├── api/             // 接口请求封装
│   ├── assets/          // 静态资源(图片、样式,参与打包)
│   ├── components/      // 通用组件(全局/业务组件)
│   ├── hooks/           // 自定义Hook(复用Composition API逻辑)
│   ├── router/          // 路由配置
│   ├── store/           // Pinia状态管理
│   ├── types/           // TypeScript类型定义
│   ├── utils/           // 工具类(axios、时间、加密等)
│   ├── views/           // 页面视图组件
│   ├── App.vue          // 根组件
│   ├── main.ts          // 入口文件
│   └── env.d.ts         // 环境类型声明
├── .eslintrc.cjs        // ESLint配置
├── .prettierrc          // Prettier配置
├── index.html           // 入口HTML(Vite特有)
├── package.json         // 依赖与脚本配置
├── tsconfig.json        // TypeScript配置
└── vite.config.ts       // Vite配置
2.1.3 核心配置文件详解

vite.config.ts(Vite 核心配置)

typescript

运行

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'

// https://vitejs.dev/config/
export default defineConfig({
  // 插件配置
  plugins: [vue()],
  // 路径别名(解决@路径引用)
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src')
    }
  },
  // 开发服务器配置
  server: {
    port: 8080, // 端口
    host: '0.0.0.0', // 允许外部访问
    open: true, // 启动后自动打开浏览器
    proxy: {
      // 接口代理(解决跨域)
      '/api': {
        target: 'http://localhost:8081', // 后端接口地址
        changeOrigin: true, // 开启跨域
        rewrite: (path) => path.replace(/^\/api/, '') // 重写路径
      }
    }
  },
  // 构建配置
  build: {
    outDir: 'dist', // 输出目录
    assetsDir: 'assets', // 静态资源目录
    minify: 'terser', // 压缩方式
    terserOptions: {
      // 移除console和debugger
      compress: {
        drop_console: true,
        drop_debugger: true
      }
    }
  }
})

tsconfig.json(TypeScript 配置)

json

{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "strict": true, // 开启严格类型检查
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "esModuleInterop": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "skipLibCheck": true,
    // 路径别名映射
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

2.2 Vue 3 核心语法:Composition API 全解析

Vue 3 的核心升级是引入 Composition API,相比 Vue 2 的 Options API,它解决了「逻辑复用难」「大型组件代码分散」的问题,核心优势是逻辑聚合类型友好

2.2.1 入口:setup 函数

setup 是 Composition API 的入口函数,执行时机在 beforeCreate 之前,此时 this 指向 undefined,不能访问 this。

vue

<template>
  <div>{{ count }} - {{ doubleCount }}</div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'

// 1. 响应式变量(基础类型)
const count = ref(0)

// 2. 计算属性
const doubleCount = computed(() => count.value * 2)

// 3. 方法
const increment = () => {
  count.value++
}

// 4. 生命周期钩子
onMounted(() => {
  console.log('组件挂载完成')
  increment()
})
</script>
2.2.2 响应式核心:ref 与 reactive
类型 适用场景 语法特点
ref 基础类型(Number/String/Boolean)、单值对象 通过.value 访问 / 修改值,模板中自动解包
reactive 复杂对象 / 数组 直接访问属性,无需.value,不支持基础类型

实战代码:ref 与 reactive 的使用与区别

vue

<template>
  <div>
    <!-- ref模板自动解包,无需.value -->
    <p>基础类型ref:{{ num }}</p>
    <!-- reactive直接访问属性 -->
    <p>复杂对象reactive:{{ user.name }} - {{ user.age }}</p>
    <!-- ref包裹对象,模板需.value(或用reactive) -->
    <p>ref包裹对象:{{ obj.value.msg }}</p>
    <button @click="updateData">更新数据</button>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive } from 'vue'

// 1. ref:基础类型
const num = ref(10)

// 2. reactive:复杂对象
const user = reactive({
  name: 'Vue开发者',
  age: 25
})

// 3. ref:包裹对象(不推荐,优先用reactive)
const obj = ref({
  msg: 'Hello Vue 3'
})

// 4. 更新数据
const updateData = () => {
  num.value += 1 // ref需.value
  user.age += 1 // reactive直接修改
  obj.value.msg = 'Updated' // ref对象需.value
}
</script>
2.2.3 计算属性:computed

computed 用于定义「基于其他响应式数据派生的属性」,具备缓存特性(仅依赖数据变化时重新计算)。

vue

<template>
  <div>
    <p>原始价格:{{ price }}</p>
    <p>折扣价格(9折):{{ discountPrice }}</p>
    <p>税后价格(13%):{{ taxPrice }}</p>
    <button @click="price += 10">提价10元</button>
  </div>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'

const price = ref(100)

// 只读计算属性(最常用)
const discountPrice = computed(() => {
  return (price.value * 0.9).toFixed(2)
})

// 可写计算属性(少用)
const taxPrice = computed({
  get: () => (price.value * 1.13).toFixed(2),
  set: (newValue) => {
    price.value = Number((Number(newValue) / 1.13).toFixed(2))
  }
})

// 触发可写计算属性的setter
const setTaxPrice = () => {
  taxPrice.value = '124.3'
}
</script>
2.2.4 侦听器:watch 与 watchEffect

watch 用于「显式监听指定响应式数据」,watchEffect 用于「隐式监听所有用到的响应式数据」,核心区别:

  • watch:懒执行(首次不执行),可获取新旧值,需指定监听源;
  • watchEffect:立即执行,自动收集依赖,无法获取旧值。

实战代码:watch 与 watchEffect

vue

<template>
  <div>
    <p>用户名:{{ user.name }}</p>
    <p>年龄:{{ user.age }}</p>
    <button @click="user.name = '新用户名'">修改用户名</button>
    <button @click="user.age += 1">增加年龄</button>
  </div>
</template>

<script setup lang="ts">
import { reactive, watch, watchEffect } from 'vue'

const user = reactive({
  name: '初始用户名',
  age: 20
})

// 1. watch:监听单个属性
watch(() => user.name, (newVal, oldVal) => {
  console.log('用户名变化:', oldVal, '→', newVal)
}, {
  immediate: true, // 首次执行
  deep: false // 基础类型无需深度监听
})

// 2. watch:监听多个属性
watch([() => user.name, () => user.age], ([newName, newAge], [oldName, oldAge]) => {
  console.log('用户名/年龄变化:', oldName, oldAge, '→', newName, newAge)
})

// 3. watch:深度监听对象(不推荐,优先监听具体属性)
watch(user, (newVal, oldVal) => {
  console.log('user对象变化', newVal)
}, { deep: true })

// 4. watchEffect:自动收集依赖
const stopWatch = watchEffect(() => {
  console.log('watchEffect:', user.name, user.age)
  // 当user.name或user.age变化时触发
})

// 停止监听(如组件卸载时)
// stopWatch()
</script>
2.2.5 生命周期钩子

Vue 3 的生命周期钩子通过「on + 钩子名」的方式调用,且 setup 中无需区分 created/beforeCreate(setup 本身替代这两个钩子)。

Vue 2 钩子 Vue 3 钩子(Composition API) 执行时机
beforeCreate setup(替代) 组件实例创建前
created setup(替代) 组件实例创建后
beforeMount onBeforeMount 组件挂载前
mounted onMounted 组件挂载后
beforeUpdate onBeforeUpdate 组件更新前
updated onUpdated 组件更新后
beforeUnmount onBeforeUnmount 组件卸载前
unmounted onUnmounted 组件卸载后
errorCaptured onErrorCaptured 捕获子组件错误时

实战代码:生命周期钩子使用

vue

<template>
  <div>生命周期演示</div>
</template>

<script setup lang="ts">
import { onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from 'vue'

// 挂载前
onBeforeMount(() => {
  console.log('组件即将挂载')
})

// 挂载后(常用:请求数据、初始化第三方库)
onMounted(() => {
  console.log('组件挂载完成')
  // 示例:请求列表数据
  // fetchData()
})

// 更新前
onBeforeUpdate(() => {
  console.log('组件即将更新')
})

// 更新后
onUpdated(() => {
  console.log('组件更新完成')
})

// 卸载前(常用:清除定时器、取消请求、关闭WebSocket)
onBeforeUnmount(() => {
  console.log('组件即将卸载')
  // 示例:清除定时器
  // clearInterval(timer)
})

// 卸载后
onUnmounted(() => {
  console.log('组件卸载完成')
})
</script>
2.2.6 组件通信:Vue 3 全方案

组件通信是 Vue 开发的核心场景,Vue 3 支持多种通信方式,适配不同场景:

通信方式 适用场景 核心语法
Props 父传子 子组件 defineProps,父组件 v-bind
Emits 子传父 子组件 defineEmits,父组件 v-on
v-model 父子双向绑定 子组件 defineProps+defineEmits,父组件 v-model
provide/inject 跨层级通信(爷孙 / 深层) 父组件 provide,子组件 inject
Pinia 全局状态共享 全局 Store,任意组件访问 / 修改
事件总线 非父子通信(Vue 3 需手动实现) mitt 库

实战 1:Props+Emits(基础父子通信)

vue

<!-- 父组件 Parent.vue -->
<template>
  <div>
    <h3>父组件:{{ parentMsg }}</h3>
    <Child 
      :msg="parentMsg" 
      @change-msg="handleChangeMsg"
    />
  </div>
</template>

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

const parentMsg = ref('父组件传递的消息')

const handleChangeMsg = (newMsg: string) => {
  parentMsg.value = newMsg
}
</script>

<!-- 子组件 Child.vue -->
<template>
  <div>
    <p>子组件接收:{{ msg }}</p>
    <button @click="sendToParent">向父组件发送消息</button>
  </div>
</template>

<script setup lang="ts">
// 定义接收的Props
const props = defineProps<{
  msg: string
}>()

// 定义触发的事件
const emit = defineEmits<{
  (e: 'change-msg', newMsg: string): void
}>()

const sendToParent = () => {
  emit('change-msg', '子组件修改后的消息')
}
</script>

实战 2:v-model(父子双向绑定)

vue

<!-- 父组件 Parent.vue -->
<template>
  <div>
    <h3>父组件v-model:{{ inputValue }}</h3>
    <Child v-model="inputValue" />
  </div>
</template>

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

const inputValue = ref('初始值')
</script>

<!-- 子组件 Child.vue -->
<template>
  <input 
    type="text" 
    :value="modelValue" 
    @input="handleInput"
  />
</template>

<script setup lang="ts">
// 定义v-model的Props(默认modelValue)
const props = defineProps<{
  modelValue: string
}>()

// 定义v-model的事件(默认update:modelValue)
const emit = defineEmits<{
  (e: 'update:modelValue', value: string): void
}>()

const handleInput = (e: Event) => {
  const target = e.target as HTMLInputElement
  emit('update:modelValue', target.value)
}
</script>

实战 3:provide/inject(跨层级通信)

vue

<!-- 根组件 App.vue -->
<template>
  <Parent />
</template>

<script setup lang="ts">
import { provide, ref } from 'vue'
import Parent from './Parent.vue'

// 提供数据(可提供响应式数据)
const theme = ref('dark')
provide('theme', theme)

// 提供方法
provide('changeTheme', (newTheme: string) => {
  theme.value = newTheme
})
</script>

<!-- 子组件 Parent.vue -->
<template>
  <Child />
</template>

<script setup lang="ts">
import Child from './Child.vue'
// 无需处理,直接透传
</script>

<!-- 孙组件 Child.vue -->
<template>
  <div :class="`theme-${theme}`">
    <p>当前主题:{{ theme }}</p>
    <button @click="changeTheme('light')">切换浅色主题</button>
  </div>
</template>

<script setup lang="ts">
import { inject } from 'vue'

// 注入数据
const theme = inject<string>('theme', 'light') // 第二个参数是默认值

// 注入方法
const changeTheme = inject<(newTheme: string) => void>('changeTheme', () => {})
</script>

<style>
.theme-dark {
  background: #333;
  color: #fff;
}
.theme-light {
  background: #fff;
  color: #333;
}
</style>

实战 4:事件总线(mitt 库)

bash

运行

# 安装mitt
npm install mitt

typescript

运行

// src/utils/bus.ts:封装事件总线
import mitt from 'mitt'

type Events = {
  'msg-change': string
  'user-login': { id: number; name: string }
}

const bus = mitt<Events>() // 类型化事件总线

export default bus

vue

<!-- 发送方组件 Sender.vue -->
<template>
  <button @click="sendMsg">发送消息</button>
</template>

<script setup lang="ts">
import bus from '@/utils/bus'

const sendMsg = () => {
  // 发送事件
  bus.emit('msg-change', '来自Sender的消息')
  bus.emit('user-login', { id: 1, name: 'Vue用户' })
}
</script>

<!-- 接收方组件 Receiver.vue -->
<template>
  <div>
    <p>接收的消息:{{ msg }}</p>
    <p>登录用户:{{ user?.name }}</p>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import bus from '@/utils/bus'

const msg = ref('')
const user = ref<{ id: number; name: string } | null>(null)

onMounted(() => {
  // 监听事件
  const msgHandler = (content: string) => {
    msg.value = content
  }
  const userHandler = (userInfo) => {
    user.value = userInfo
  }

  bus.on('msg-change', msgHandler)
  bus.on('user-login', userHandler)

  // 组件卸载时移除监听(避免内存泄漏)
  onUnmounted(() => {
    bus.off('msg-change', msgHandler)
    bus.off('user-login', userHandler)
  })
})
</script>

2.3 Vue 3 响应式原理深度解析

Vue 3 的响应式系统基于 ES6 的 Proxy 实现,核心分为「依赖收集」和「触发更新」两个阶段。

2.3.1 核心原理简化实现

typescript

运行

// 简化版响应式原理(理解用)
// 1. 存储依赖的映射:target -> key -> effect函数
const targetMap = new WeakMap<object, Map<string | symbol, Set<Function>>>()

// 2. 当前活跃的effect函数
let activeEffect: Function | null = null

// 3. effect函数:执行并收集依赖
function effect(fn: Function) {
  activeEffect = fn
  // 执行fn,触发Proxy的getter,收集依赖
  fn()
  activeEffect = null
}

// 4. 收集依赖
function track(target: object, key: string | symbol) {
  if (!activeEffect) return
  // 获取target的依赖映射
  let depsMap = targetMap.get(target)
  if (!depsMap) {
    depsMap = new Map()
    targetMap.set(target, depsMap)
  }
  // 获取key的effect集合
  let deps = depsMap.get(key)
  if (!deps) {
    deps = new Set()
    depsMap.set(key, deps)
  }
  // 添加当前effect到集合
  deps.add(activeEffect)
}

// 5. 触发更新
function trigger(target: object, key: string | symbol) {
  // 获取target的依赖映射
  const depsMap = targetMap.get(target)
  if (!depsMap) return
  // 获取key的effect集合
  const deps = depsMap.get(key)
  if (!deps) return
  // 执行所有effect
  deps.forEach(fn => fn())
}

// 6. 响应式核心:Proxy
function reactive<T extends object>(target: T): T {
  return new Proxy(target, {
    get(target, key, receiver) {
      const res = Reflect.get(target, key, receiver)
      // 收集依赖
      track(target, key)
      return res
    },
    set(target, key, value, receiver) {
      const oldValue = Reflect.get(target, key, receiver)
      const res = Reflect.set(target, key, value, receiver)
      // 只有值变化时触发更新
      if (oldValue !== value) {
        trigger(target, key)
      }
      return res
    }
  })
}

// 测试
const obj = reactive({ count: 0 })

// 定义effect,当count变化时执行
effect(() => {
  console.log('count变化:', obj.count)
})

obj.count++ // 输出:count变化:1
obj.count++ // 输出:count变化:2
2.3.2 ref 的底层实现

ref 的底层是对基础类型的「包裹对象」,通过 Proxy 监听.value 属性:

typescript

运行

function ref<T>(value: T) {
  // 包裹对象
  const wrapper = {
    _value: value
  }
  // 转为响应式
  return new Proxy(wrapper, {
    get(target, key) {
      if (key === 'value') {
        track(target, '_value')
        return target._value
      }
      return Reflect.get(target, key)
    },
    set(target, key, value) {
      if (key === 'value') {
        target._value = value
        trigger(target, '_value')
        return true
      }
      return Reflect.set(target, key, value)
    }
  })
}

三、Vue 工程化开发:从路由到状态管理

3.1 Vue Router 4:单页应用核心

Vue Router 是 Vue 官方的路由管理器,实现单页应用(SPA)的页面跳转,Vue 3 适配 Vue Router 4。

3.1.1 路由基础配置

bash

运行

# 安装Vue Router 4
npm install vue-router@4

typescript

运行

// src/router/index.ts:路由核心配置
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import Home from '@/views/Home.vue'
import Login from '@/views/Login.vue'

// 静态路由(无需权限)
export const constantRoutes: RouteRecordRaw[] = [
  {
    path: '/',
    redirect: '/home' // 重定向
  },
  {
    path: '/home',
    name: 'Home',
    component: Home,
    meta: {
      title: '首页',
      keepAlive: true // 开启缓存
    }
  },
  {
    path: '/login',
    name: 'Login',
    component: Login,
    hidden: true // 侧边栏隐藏
  },
  {
    path: '/detail/:id', // 动态路由参数
    name: 'Detail',
    component: () => import('@/views/Detail.vue'), // 懒加载
    props: true // 开启props传参
  },
  {
    path: '/:pathMatch(.*)*', // 404路由
    name: 'NotFound',
    component: () => import('@/views/NotFound.vue')
  }
]

// 创建路由实例
const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL), // HTML5 History模式
  routes: constantRoutes,
  scrollBehavior(to, from, savedPosition) {
    // 滚动行为:返回顶部
    return savedPosition || { top: 0 }
  }
})

export default router

typescript

运行

// src/main.ts:注册路由
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

const app = createApp(App)
app.use(router)
app.mount('#app')

vue

<!-- src/App.vue:路由出口 -->
<template>
  <router-view />
</template>
3.1.2 路由核心功能实战

实战 1:路由跳转与传参

vue

<!-- 声明式跳转 -->
<template>
  <div>
    <!-- 基础跳转 -->
    <router-link to="/home">首页</router-link>
    <!-- 动态参数跳转 -->
    <router-link :to="{ name: 'Detail', params: { id: 1 } }">详情页</router-link>
    <!-- 查询参数跳转 -->
    <router-link :to="{ path: '/detail/1', query: { type: 'vue' } }">带查询参数的详情页</router-link>
  </div>
</template>

<!-- 编程式跳转 -->
<script setup lang="ts">
import { useRouter, useRoute } from 'vue-router'

// 获取路由实例
const router = useRouter()
// 获取当前路由信息
const route = useRoute()

// 基础跳转
const toHome = () => {
  router.push('/home')
}

// 命名路由跳转(推荐)
const toDetail = () => {
  router.push({
    name: 'Detail',
    params: { id: 1 },
    query: { type: 'vue' }
  })
}

// 替换历史记录(不新增历史条目)
const replaceToHome = () => {
  router.replace('/home')
}

// 前进/后退
const goBack = () => {
  router.go(-1) // 后退一步
}

// 获取参数
console.log(route.params.id) // 动态参数
console.log(route.query.type) // 查询参数
</script>

实战 2:路由守卫(权限控制)路由守卫分为「全局守卫」「路由独享守卫」「组件内守卫」,核心用于权限控制、登录验证、页面标题设置等。

typescript

运行

// src/router/index.ts:全局守卫
// 1. 全局前置守卫(常用:登录验证)
router.beforeEach((to, from, next) => {
  // 设置页面标题
  if (to.meta.title) {
    document.title = to.meta.title as string
  }
  // 登录验证:访问需要登录的路由,未登录则跳转登录页
  const isLogin = localStorage.getItem('token')
  const needLogin = !to.path.includes('/login') // 除了登录页都需要登录
  if (needLogin && !isLogin) {
    next('/login')
  } else {
    next() // 放行
  }
})

// 2. 全局解析守卫
router.beforeResolve((to, from, next) => {
  // 在所有组件内守卫和异步路由组件解析之后执行
  next()
})

// 3. 全局后置守卫(无next,用于统计、埋点)
router.afterEach((to, from) => {
  console.log('页面跳转完成:', from.path, '→', to.path)
})

typescript

运行

// 路由独享守卫
const routes = [
  {
    path: '/home',
    component: Home,
    beforeEnter: (to, from, next) => {
      // 仅对当前路由生效
      console.log('进入首页前执行')
      next()
    }
  }
]

vue

<!-- 组件内守卫 -->
<template>
  <div>详情页</div>
</template>

<script setup lang="ts">
import { onBeforeRouteEnter, onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue-router'

// 进入组件前(此时组件实例未创建,无法访问this/setup变量)
onBeforeRouteEnter((to, from, next) => {
  console.log('进入详情页前')
  // 通过next回调访问组件实例
  next(vm => {
    console.log('组件实例:', vm)
  })
})

// 路由参数更新时(如从/detail/1到/detail/2)
onBeforeRouteUpdate((to, from, next) => {
  console.log('详情页参数更新:', from.params.id, '→', to.params.id)
  next()
})

// 离开组件前(常用:确认是否离开)
onBeforeRouteLeave((to, from, next) => {
  const confirm = window.confirm('是否确认离开?')
  if (confirm) {
    next()
  } else {
    next(false) // 取消离开
  }
})
</script>
3.1.3 路由懒加载与代码分割

路由懒加载通过「动态 import」实现,减少首屏加载体积,提升加载速度:

typescript

运行

// 基础懒加载
const Home = () => import('@/views/Home.vue')

// 带分组的懒加载(打包时合并到同一chunk)
const Home = () => import(/* webpackChunkName: "home" */ '@/views/Home.vue')
const About = () => import(/* webpackChunkName: "home" */ '@/views/About.vue')

3.2 Pinia:新一代状态管理

Pinia 是 Vue 官方推荐的状态管理库,替代 Vuex,核心优势:

  • 支持 Vue 2/Vue 3,无需嵌套模块,扁平化设计;
  • 原生 TypeScript 支持,类型推断完善;
  • 简化 API,无需 mutations,直接修改状态;
  • 支持组合式 API,逻辑复用更灵活;
  • 体积更小(约 1KB),性能更优。
3.2.1 Pinia 基础配置

bash

运行

# 安装Pinia
npm install pinia

typescript

运行

// src/store/index.ts:创建Pinia实例
import { createPinia } from 'pinia'

const pinia = createPinia()

export default pinia

typescript

运行

// src/main.ts:注册Pinia
import { createApp } from 'vue'
import App from './App.vue'
import pinia from './store'

const app = createApp(App)
app.use(pinia)
app.mount('#app')
3.2.2 Pinia 核心用法:定义 Store

typescript

运行

// src/store/modules/user.ts:用户Store
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import request from '@/utils/request'

// 定义Store(第一个参数是唯一ID)
export const useUserStore = defineStore('user', () => {
  // 1. 状态(替代Vuex的state)
  const token = ref(localStorage.getItem('token') || '')
  const userInfo = ref<{ id: number; name: string; avatar: string } | null>(null)

  // 2. 计算属性(替代Vuex的getters)
  const isLogin = computed(() => !!token.value)
  const userName = computed(() => userInfo.value?.name || '未登录')

  // 3. 方法(替代Vuex的actions,支持同步/异步)
  const login = async (username: string, password: string) => {
    const res = await request.post('/api/auth/login', { username, password })
    token.value = res.data.accessToken
    // 持久化Token
    localStorage.setItem('token', token.value)
    // 获取用户信息
    await getUserInfo()
  }

  const getUserInfo = async () => {
    const res = await request.get('/api/user/info')
    userInfo.value = res.data
  }

  const logout = () => {
    token.value = ''
    userInfo.value = null
    localStorage.removeItem('token')
  }

  // 暴露状态、计算属性、方法
  return {
    token,
    userInfo,
    isLogin,
    userName,
    login,
    getUserInfo,
    logout
  }
})
3.2.3 Pinia 组件使用

vue

<template>
  <div>
    <p>用户名:{{ userName }}</p>
    <p v-if="isLogin">已登录</p>
    <button v-if="!isLogin" @click="handleLogin">登录</button>
    <button v-else @click="handleLogout">退出登录</button>
  </div>
</template>

<script setup lang="ts">
import { useUserStore } from '@/store/modules/user'

// 获取Store实例
const userStore = useUserStore()

// 访问状态(直接访问,无需.value)
const { userName, isLogin } = userStore

// 方法调用
const handleLogin = async () => {
  await userStore.login('admin', '123456')
}

const handleLogout = () => {
  userStore.logout()
}
</script>
3.2.4 Pinia 高级特性

实战 1:Store 持久化(pinia-plugin-persistedstate)

bash

运行

# 安装持久化插件
npm install pinia-plugin-persistedstate

typescript

运行

// src/store/index.ts:注册插件
import { createPinia } from 'pinia'
import persist from 'pinia-plugin-persistedstate'

const pinia = createPinia()
pinia.use(persist)

export default pinia

typescript

运行

// src/store/modules/user.ts:开启持久化
export const useUserStore = defineStore('user', () => {
  // ... 状态定义
}, {
  // 持久化配置
  persist: {
    key: 'user-store', // 存储的key
    storage: localStorage, // 存储方式(localStorage/sessionStorage)
    paths: ['token', 'userInfo.name'] // 只持久化token和userInfo.name
  }
})

实战 2:Store 间通信

typescript

运行

// src/store/modules/cart.ts:购物车Store
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { useUserStore } from './user'

export const useCartStore = defineStore('cart', () => {
  const cartList = ref<{ id: number; name: string; price: number }[]>([])

  // 依赖其他Store
  const userStore = useUserStore()

  // 添加商品(仅登录用户可操作)
  const addGoods = (goods: { id: number; name: string; price: number }) => {
    if (!userStore.isLogin) {
      alert('请先登录')
      return
    }
    cartList.value.push(goods)
  }

  return {
    cartList,
    addGoods
  }
})

实战 3:批量修改状态($patch)

vue

<script setup lang="ts">
import { useCartStore } from '@/store/modules/cart'

const cartStore = useCartStore()

// 批量修改状态(性能更优)
const batchUpdateCart = () => {
  cartStore.$patch({
    cartList: [
      ...cartStore.cartList,
      { id: 2, name: 'Vue实战教程', price: 99 }
    ]
  })

  // 或函数式修改(适合复杂逻辑)
  cartStore.$patch((state) => {
    state.cartList.push({ id: 3, name: 'Pinia教程', price: 88 })
  })
}
</script>

四、Vue 企业级实战:组件封装、性能优化与跨端

4.1 通用组件封装:从基础到高阶

组件封装是 Vue 工程化的核心,优秀的组件需满足「高内聚、低耦合、可复用、可配置」的原则。

4.1.1 基础组件封装:通用按钮

vue

<!-- src/components/MyButton.vue -->
<template>
  <button
    class="my-button"
    :class="[
      `my-button--${type}`,
      `my-button--${size}`,
      { 'my-button--disabled': disabled },
      { 'my-button--loading': loading }
    ]"
    :disabled="disabled || loading"
    @click="handleClick"
  >
    <span v-if="loading" class="my-button__loading"></span>
    <slot></slot>
  </button>
</template>

<script setup lang="ts">
// 定义Props
const props = defineProps<{
  type: 'primary' | 'success' | 'warning' | 'danger' | 'default'
  size: 'large' | 'medium' | 'small'
  disabled?: boolean
  loading?: boolean
}>()

// 默认值
withDefaults(props, {
  type: 'default',
  size: 'medium',
  disabled: false,
  loading: false
})

// 定义Emits
const emit = defineEmits<{
  (e: 'click', evt: MouseEvent): void
}>()

// 点击事件
const handleClick = (evt: MouseEvent) => {
  if (!props.disabled && !props.loading) {
    emit('click', evt)
  }
}
</script>

<style scoped>
.my-button {
  border: none;
  border-radius: 4px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 16px;
  font-size: 14px;
  transition: all 0.2s;
}

/* 类型样式 */
.my-button--default {
  background: #fff;
  color: #333;
  border: 1px solid #ddd;
}
.my-button--primary {
  background: #409eff;
  color: #fff;
}
.my-button--success {
  background: #67c23a;
  color: #fff;
}
.my-button--warning {
  background: #e6a23c;
  color: #fff;
}
.my-button--danger {
  background: #f56c6c;
  color: #fff;
}

/* 大小样式 */
.my-button--large {
  height: 40px;
  font-size: 16px;
}
.my-button--medium {
  height: 32px;
}
.my-button--small {
  height: 24px;
  font-size: 12px;
  padding: 0 8px;
}

/* 禁用/加载样式 */
.my-button--disabled, .my-button--loading {
  cursor: not-allowed;
  opacity: 0.6;
}

.my-button__loading {
  width: 14px;
  height: 14px;
  border: 2px solid #fff;
  border-top: 2px solid transparent;
  border-radius: 50%;
  animation: loading 1s linear infinite;
  margin-right: 8px;
}

@keyframes loading {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
</style>
4.1.2 高阶组件封装:表格组件

vue

<!-- src/components/MyTable.vue -->
<template>
  <div class="my-table">
    <table>
      <thead>
        <tr>
          <th v-for="column in columns" :key="column.prop" :width="column.width">
            {{ column.label }}
          </th>
          <th v-if="showAction" width="120">操作</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="(row, index) in data" :key="row[props.rowKey] || index">
          <td v-for="column in columns" :key="column.prop">
            <!-- 自定义列内容 -->
            <slot :name="`cell-${column.prop}`" :row="row" :index="index">
              {{ row[column.prop] }}
            </slot>
          </td>
          <td v-if="showAction">
            <slot name="action" :row="row" :index="index"></slot>
          </td>
        </tr>
        <tr v-if="data.length === 0">
          <td :colspan="columns.length + (showAction ? 1 : 0)" class="empty">
            {{ emptyText }}
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script setup lang="ts">
// 定义列类型
interface TableColumn {
  prop: string
  label: string
  width?: string | number
}

// 定义Props
const props = defineProps<{
  columns: TableColumn[]
  data: Record<string, any>[]
  rowKey?: string
  showAction?: boolean
  emptyText?: string
}>()

// 默认值
withDefaults(props, {
  rowKey: 'id',
  showAction: false,
  emptyText: '暂无数据'
})
</script>

<style scoped>
.my-table {
  width: 100%;
  border: 1px solid #eee;
  border-radius: 4px;
  overflow: hidden;
}

.my-table table {
  width: 100%;
  border-collapse: collapse;
}

.my-table th, .my-table td {
  padding: 12px;
  border-bottom: 1px solid #eee;
  text-align: left;
}

.my-table th {
  background: #f5f5f5;
  font-weight: 600;
}

.my-table .empty {
  text-align: center;
  color: #999;
  padding: 40px 0;
}
</style>

组件使用示例

vue

<template>
  <MyTable
    :columns="columns"
    :data="tableData"
    show-action
  >
    <!-- 自定义列:状态 -->
    <template #cell-status="{ row }">
      <span :class="`status-${row.status}`">
        {{ row.status === 'active' ? '活跃' : '禁用' }}
      </span>
    </template>

    <!-- 操作列 -->
    <template #action="{ row }">
      <MyButton type="primary" size="small" @click="editRow(row)">编辑</MyButton>
      <MyButton type="danger" size="small" @click="deleteRow(row)">删除</MyButton>
    </template>
  </MyTable>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import MyTable from '@/components/MyTable.vue'
import MyButton from '@/components/MyButton.vue'

// 列配置
const columns = ref([
  { prop: 'name', label: '姓名', width: '100px' },
  { prop: 'age', label: '年龄', width: '80px' },
  { prop: 'status', label: '状态' }
])

// 表格数据
const tableData = ref([
  { id: 1, name: 'Vue开发者', age: 25, status: 'active' },
  { id: 2, name: 'Pinia爱好者', age: 30, status: 'disabled' }
])

// 编辑行
const editRow = (row) => {
  console.log('编辑:', row)
}

// 删除行
const deleteRow = (row) => {
  tableData.value = tableData.value.filter(item => item.id !== row.id)
}
</script>

<style scoped>
.status-active {
  color: #67c23a;
}
.status-disabled {
  color: #999;
}
</style>

4.2 Vue 性能优化:从代码到构建

Vue 项目的性能优化需覆盖「代码层面」「构建层面」「运行时层面」,核心目标是「减少加载时间」「提升渲染性能」「降低内存占用」。

4.2.1 代码层面优化
1. 响应式数据优化
  • 避免响应式数据嵌套过深:reactive 嵌套层级建议不超过 3 层;
  • 非响应式数据无需 ref/reactive:如常量、一次性数据;
  • 使用 shallowRef/shallowReactive:仅监听浅层属性,适合大型对象。

vue

<script setup lang="ts">
import { shallowRef, shallowReactive } from 'vue'

// 浅层响应式:仅监听obj.value的引用变化,不监听内部属性
const obj = shallowRef({ a: 1, b: { c: 2 } })
obj.value.a = 2 // 不触发更新
obj.value = { a: 3 } // 触发更新

// 浅层响应式:仅监听对象第一层属性
const user = shallowReactive({
  name: 'Vue',
  info: { age: 3 }
})
user.name = 'Vue 3' // 触发更新
user.info.age = 4 // 不触发更新
</script>
2. 渲染优化
  • v-for 优化:必须加 key,避免使用 index 作为 key;
  • v-if 与 v-for 优先级:避免同时使用(v-for 优先级更高,可将 v-if 提至外层);
  • 虚拟列表:长列表使用 vue-virtual-scroller,只渲染可视区域;
  • 避免不必要的渲染:使用 v-once、computed 缓存、memo 组件。

vue

<!-- v-for优化 -->
<template>
  <div v-for="item in list" :key="item.id">
    {{ item.name }}
  </div>

  <!-- v-if与v-for分离 -->
  <template v-if="showList">
    <div v-for="item in list" :key="item.id">
      {{ item.name }}
    </div>
  </template>

  <!-- v-once:只渲染一次 -->
  <div v-once>{{ staticData }}</div>

  <!-- memo:仅依赖变化时重新渲染 -->
  <MyComponent v-memo="[props.a, props.b]" />
</template>
3. 事件与监听优化
  • 移除无用的事件监听:组件卸载时移除 window / 第三方库的监听;
  • 防抖 / 节流:高频事件(resize、scroll、input)添加防抖节流;

vue

<template>
  <input @input="handleInput" />
</template>

<script setup lang="ts">
import { onUnmounted } from 'vue'
import { debounce } from 'lodash-es'

// 防抖处理
const handleInput = debounce((e) => {
  console.log(e.target.value)
}, 300)

// 移除监听
onUnmounted(() => {
  handleInput.cancel()
})
</script>
4.2.2 构建层面优化
1. 按需引入
  • UI 组件库按需引入:如 Element Plus、Ant Design Vue;
  • 第三方库按需引入:如 lodash、echarts。

typescript

运行

// src/main.ts:Element Plus按需引入
import { createApp } from 'vue'
import App from './App.vue'
import { ElButton, ElTable } from 'element-plus'
import 'element-plus/es/components/button/style/css'
import 'element-plus/es/components/table/style/css'

const app = createApp(App)
app.component('ElButton', ElButton)
app.component('ElTable', ElTable)
app.mount('#app')
2. 资源压缩
  • 开启 gzip/brotli 压缩:Nginx 配置或 Vite 插件;
  • 图片压缩:使用 vite-plugin-imagemin;
  • 代码压缩:Vite 默认开启 terser 压缩,移除 console/debugger。

typescript

运行

// vite.config.ts:开启gzip压缩
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import viteCompression from 'vite-plugin-compression'

export default defineConfig({
  plugins: [
    vue(),
    // gzip压缩
    viteCompression({
      algorithm: 'gzip',
      threshold: 10240, // 大于10KB的文件压缩
      deleteOriginFile: false // 不删除原文件
    }),
    // brotli压缩(比gzip更优)
    viteCompression({
      algorithm: 'brotliCompress',
      ext: '.br',
      threshold: 10240
    })
  ]
})
3. 分包策略
  • 拆分第三方库:将 node_modules 拆分为单独的 chunk;
  • 拆分页面:不同页面拆分为不同的 chunk;

typescript

运行

// vite.config.ts:分包策略
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  build: {
    rollupOptions: {
      output: {
        // 分包
        manualChunks: {
          // 第三方库拆分
          vendor: ['vue', 'vue-router', 'pinia'],
          utils: ['lodash-es', 'axios']
        }
      }
    }
  }
})
4.2.3 运行时优化
1. 路由懒加载(已在 3.1.3 实现)
2. 缓存优化
  • 组件缓存:使用 keep-alive 缓存频繁切换的组件;
  • 接口缓存:使用 axios 拦截器缓存 GET 请求结果;

vue

<!-- keep-alive缓存组件 -->
<template>
  <keep-alive include="Home,Detail" exclude="Login">
    <router-view />
  </keep-alive>
</template>

typescript

运行

// src/utils/request.ts:接口缓存
import axios from 'axios'

// 缓存容器
const cache = new Map()

const request = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL
})

// 请求拦截器:缓存GET请求
request.interceptors.request.use((config) => {
  if (config.method === 'get') {
    const key = JSON.stringify({
      url: config.url,
      params: config.params
    })
    // 缓存命中,直接返回缓存数据
    if (cache.has(key)) {
      return Promise.reject({
        type: 'cache',
        data: cache.get(key)
      })
    }
  }
  return config
})

// 响应拦截器:存储GET请求缓存
request.interceptors.response.use((response) => {
  if (response.config.method === 'get') {
    const key = JSON.stringify({
      url: response.config.url,
      params: response.config.params
    })
    cache.set(key, response.data)
    // 设置缓存过期时间(5分钟)
    setTimeout(() => {
      cache.delete(key)
    }, 300000)
  }
  return response
}, (error) => {
  // 缓存命中的错误处理
  if (error.type === 'cache') {
    return Promise.resolve({ data: error.data })
  }
  return Promise.reject(error)
})

export default request

4.3 Vue 跨端开发:从 Web 到移动端

Vue 的跨端生态完善,可通过不同方案实现「一套代码多端运行」:

4.3.1 Vue + Vant:移动端 Web 开发

Vant 是有赞开源的移动端 UI 组件库,适配 Vue 2/Vue 3,核心优势:轻量、易用、适配性好。

bash

运行

# 安装Vant 4(适配Vue 3)
npm install vant

typescript

运行

// src/main.ts:按需引入Vant
import { createApp } from 'vue'
import App from './App.vue'
import { Button, Cell, List } from 'vant'
import 'vant/lib/index.css'

const app = createApp(App)
app.use(Button)
app.use(Cell)
app.use(List)
app.mount('#app')
4.3.2 UniApp:Vue 跨端开发(小程序 / APP/H5)

UniApp 是基于 Vue 的跨端框架,支持一套代码编译为微信小程序、支付宝小程序、APP、H5 等。

  • 核心语法:Vue 2/Vue 3(推荐 Vue 3 + Vite);
  • 组件:扩展 Vue 组件,新增小程序特有的组件(如 swiper、picker);
  • API:封装多端统一的 API(如 uni.request、uni.navigateTo)。
4.3.3 Vue + Electron:桌面应用开发

Electron 是基于 Chromium 和 Node.js 的桌面应用框架,可将 Vue 项目打包为 Windows/Mac/Linux 应用。

bash

运行

# 安装Electron
npm install electron --save-dev

javascript

运行

// electron/main.js:主进程
const { app, BrowserWindow } = require('electron')
const path = require('path')

function createWindow() {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      nodeIntegration: true
    }
  })

  // 加载Vue项目的dist目录
  win.loadFile('dist/index.html')
  // 开启开发者工具
  win.webContents.openDevTools()
}

app.whenReady().then(() => {
  createWindow()
  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit()
})

五、Vue 测试与部署:企业级工程闭环

5.1 Vue 单元测试:Vue Test Utils

Vue Test Utils 是 Vue 官方的单元测试库,适配 Vue 3,支持 Jest/Vitest。

bash

运行

# 安装依赖
npm install @vue/test-utils vitest jsdom --save-dev

typescript

运行

// vitest.config.ts:配置
import { defineConfig } from 'vitest/config'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  test: {
    environment: 'jsdom',
    globals: true
  }
})

typescript

运行

// src/components/MyButton.test.ts:按钮组件测试
import { mount } from '@vue/test-utils'
import { describe, it, expect } from 'vitest'
import MyButton from './MyButton.vue'

describe('MyButton.vue', () => {
  // 测试默认渲染
  it('renders default button', () => {
    const wrapper = mount(MyButton, {
      slots: {
        default: '默认按钮'
      }
    })
    expect(wrapper.text()).toBe('默认按钮')
    expect(wrapper.classes()).toContain('my-button--default')
  })

  // 测试类型
  it('renders primary button', () => {
    const wrapper = mount(MyButton, {
      props: {
        type: 'primary'
      }
    })
    expect(wrapper.classes()).toContain('my-button--primary')
  })

  // 测试点击事件
  it('emits click event', async () => {
    const wrapper = mount(MyButton)
    await wrapper.trigger('click')
    expect(wrapper.emitted('click')).toBeTruthy()
  })

  // 测试禁用状态
  it('disabled button not emit click', async () => {
    const wrapper = mount(MyButton, {
      props: {
        disabled: true
      }
    })
    await wrapper.trigger('click')
    expect(wrapper.emitted('click')).toBeFalsy()
  })
})

5.2 Vue 项目部署:从打包到上线

5.2.1 打包构建

bash

运行

# 生产环境打包
npm run build

打包完成后生成 dist 目录,包含静态 HTML/CSS/JS 文件。

5.2.2 Nginx 部署

nginx

# nginx.conf配置
server {
  listen 80;
  server_name vue-demo.com;

  # 根目录指向dist
  root /usr/share/nginx/html/vue-demo/dist;
  index index.html;

  # 解决SPA路由刷新404
  location / {
    try_files $uri $uri/ /index.html;
  }

  # 开启gzip压缩
  gzip on;
  gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

  # 静态资源缓存
  location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
    expires 30d;
    add_header Cache-Control "public, max-age=2592000";
  }
}
5.2.3 容器化部署(Docker)

dockerfile

# Dockerfile
# 阶段1:构建
FROM node:18-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# 阶段2:部署
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

bash

运行

# 构建镜像
docker build -t vue-demo:v1 .

# 运行容器
docker run -d -p 80:80 --name vue-demo vue-demo:v1

六、学习总结与进阶方向

6.1 学习总结

本学期围绕 Vue.js 的学习,从基础语法到企业级实战,核心收获:

  1. 核心原理层面:理解了 Vue 3 的响应式原理(Proxy)、虚拟 DOM、编译优化,掌握了 Composition API 的设计思想;
  2. 工程化层面:掌握了 Vite 构建、路由管理、状态管理、组件封装的企业级规范,能够搭建完整的 Vue 工程体系;
  3. 性能优化层面:掌握了从代码、构建、运行时的全维度优化技巧,能够解决实际项目中的性能瓶颈;
  4. 实战能力层面:能够独立开发组件、处理复杂业务逻辑、实现跨端适配,具备了企业级 Vue 开发的核心能力。

6.2 进阶方向

  1. 源码深度解析:深入学习 Vue 3 源码,理解编译过程、虚拟 DOMdiff 算法、响应式系统的底层实现;
  2. 跨端框架深入:深入学习 UniApp、Taro 等跨端框架,掌握多端适配的核心技巧;
  3. 前端工程化进阶:学习 Monorepo、微前端、CI/CD 等高级工程化方案;
  4. 性能优化进阶:学习 Web Worker、SSR(服务端渲染)、SSG(静态站点生成)等高级优化手段;
  5. Vue 生态扩展:学习 VueUse(Vue 工具库)、Nuxt.js(Vue 服务端渲染框架)等生态工具。
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐