Skip to content

Vue 学习文档


核心要点(TL;DR)

  • Vue 是渐进式框架,Vue 3 用 Proxy 实现响应式,解决了 Vue 2 Object.defineProperty 对对象新增/数组索引监听的局限。
  • 虚拟 DOM + Diff 算法通过同层/双端比较找出最小更新,稳定唯一的 key 是复用节点的前提。
  • Composition API 按逻辑组织代码,ref 适合基本类型,reactive 适合对象,模板中 ref 自动解包。
  • 路由优先 History 模式需服务端配置,全局状态推荐 Pinia,长列表与异步组件是常用性能优化手段。
  • 新项目推荐 Vue 3 + Vite + TypeScript + <script setup>,避免用索引当 key 与滥用 reactive

学习时长与前置知识

  • 建议学习时长:4-6 周(每周投入 6-8 小时)
  • 前置知识:JavaScript、ES6+、前端工程化基础

一、前言:Vue 的哲学

Vue 是一款渐进式 JavaScript 框架。所谓"渐进式",就是你可以根据项目需要逐步引入它的功能。小到在一个静态页面中增强某个交互,大到构建复杂的单页应用,Vue 都能胜任。

Vue 的设计哲学是"简单优雅、渐进增强"。它提供了响应式数据绑定、组件化开发、声明式渲染等核心能力,同时保留了足够的灵活性。

生活化比喻:Vue 像是一把瑞士军刀。你只需要一把小刀时,它不会强迫你打开所有工具;当你需要剪刀、螺丝刀时,它也能随时提供。

二、Vue 2 与 Vue 3 的响应式原理

2.1 Vue 2:Object.defineProperty

Vue 2 使用 Object.defineProperty 实现响应式。它遍历对象的每个属性,把它们转换成 getter/setter。

javascript
function defineReactive(obj, key, val) {
  Object.defineProperty(obj, key, {
    get() {
      console.log('读取', key);
      return val;
    },
    set(newVal) {
      console.log('设置', key);
      val = newVal;
      // 通知依赖更新
    }
  });
}

局限性:

  • 无法监听对象新增的属性(需要用 Vue.set
  • 无法监听数组通过索引修改和 length 变化
  • 需要递归遍历对象,性能开销较大

2.2 Vue 3:Proxy

Vue 3 使用 ES6 的 Proxy 实现响应式。Proxy 可以代理整个对象,监听更多操作。

javascript
const reactive = (target) => {
  return new Proxy(target, {
    get(target, key) {
      console.log('读取', key);
      return target[key];
    },
    set(target, key, value) {
      console.log('设置', key);
      target[key] = value;
      // 触发更新
      return true;
    }
  });
};

优势:

  • 可以监听新增和删除属性
  • 可以监听数组索引和长度变化
  • 不需要递归遍历,性能更好
  • 支持 Map、Set 等数据结构

三、虚拟 DOM 与 Diff 算法

3.1 什么是虚拟 DOM?

虚拟 DOM(Virtual DOM)是用 JavaScript 对象描述真实 DOM 结构的一种技术。

javascript
const vnode = {
  tag: 'div',
  props: { id: 'app' },
  children: [
    { tag: 'h1', props: {}, children: ['Hello'] }
  ]
};

3.2 为什么需要虚拟 DOM?

直接操作真实 DOM 代价高昂。虚拟 DOM 可以:

  • 减少直接 DOM 操作次数
  • 通过 Diff 算法找出最小更新
  • 跨平台渲染(如小程序、Native)

生活化比喻:真实 DOM 像是实体建筑,修改起来成本高;虚拟 DOM 像是建筑模型,先在模型上规划好改动,再一次性施工。

3.3 Vue 的 Diff 算法

Vue 的 Diff 算法采用"同层比较"策略:

  1. 新旧节点类型不同:直接替换
  2. 新旧节点类型相同:比较属性和子节点
  3. 子节点使用双端比较算法,尽量复用已有节点

Vue 2 使用"双端比较",Vue 3 进一步优化,采用"快速 Diff",处理首尾相同节点后,再处理中间变化的节点。

3.4 key 的重要性

key 是 Diff 算法识别节点的依据。使用稳定的 key 可以帮助 Vue 复用节点,避免不必要的销毁和重建。

html
<ul>
  <li v-for="item in list" :key="item.id">&#123;&#123; item.name &#125;&#125;</li>
</ul>

常见误区:使用数组索引作为 key。当列表顺序变化时,索引 key 会导致 Vue 错误复用节点,引发 bug。

四、Composition API

4.1 为什么引入 Composition API?

Vue 2 的 Options API 把数据、方法、计算属性、生命周期分散在不同选项中。当组件逻辑复杂时,相关代码被拆散,难以维护。

Composition API 允许我们按逻辑组织代码,把相关功能放在一起。

4.2 核心 API

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

const count = ref(0);
const double = computed(() => count.value * 2);

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

watch(count, (newVal) => {
  console.log('count changed:', newVal);
});

onMounted(() => {
  console.log('mounted');
});
</script>

4.3 ref 与 reactive

  • ref:用于基本类型和需要重新赋值的场景,访问时需要 .value
  • reactive:用于对象类型,访问时无需 .value,但不能直接替换整个对象

4.4 生命周期钩子

Options APIComposition API
beforeCreatesetup
createdsetup
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeUnmountonBeforeUnmount
unmountedonUnmounted

五、Vue Router

5.1 路由模式

Vue Router 支持两种模式:

  • Hash 模式:使用 URL hash,不会发送给服务器,兼容性好
  • History 模式:使用 HTML5 History API,URL 更美观,但需要服务器配置支持
javascript
const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/', component: Home },
    { path: '/about', component: About }
  ]
});

5.2 路由守卫

路由守卫用于权限控制、登录校验等场景。

javascript
router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth && !isLoggedIn()) {
    next('/login');
  } else {
    next();
  }
});

六、Pinia

6.1 什么是 Pinia?

Pinia 是 Vue 官方推荐的状态管理库,替代 Vuex。它 API 更简单,支持 TypeScript,模块化更好。

javascript
import { defineStore } from 'pinia';

export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),
  getters: {
    double: (state) => state.count * 2
  },
  actions: {
    increment() {
      this.count++;
    }
  }
});

6.2 Setup Store

Pinia 也支持 Composition API 风格:

javascript
export const useCounterStore = defineStore('counter', () => {
  const count = ref(0);
  const double = computed(() => count.value * 2);
  function increment() {
    count.value++;
  }
  return { count, double, increment };
});

七、Vue 性能优化

7.1 常用优化手段

  • v-once:只渲染一次,跳过更新
  • v-memo:Vue 3 新增,缓存子树
  • computed:缓存计算结果
  • keep-alive:缓存组件状态
  • 异步组件:defineAsyncComponent
  • 虚拟列表:处理长列表
  • 合理使用 key
vue
<template>
  <div v-once>&#123;&#123; heavyContent &#125;&#125;</div>
</template>

7.2 避免不必要的响应式

不是所有数据都需要响应式。对于不会变化的配置数据,可以用 Object.freezemarkRaw 避免响应式开销。

八、Vite + Vue 3 工程实践

8.1 为什么选择 Vite + Vue 3?

  • Vite 启动快、热更新快
  • Vue 3 性能更好、TypeScript 支持更好
  • Composition API 更适合复杂逻辑组织

8.2 项目结构

my-vue-app/
├── src/
│   ├── assets/
│   ├── components/
│   ├── composables/
│   ├── router/
│   ├── stores/
│   ├── views/
│   ├── App.vue
│   └── main.js
├── index.html
├── package.json
└── vite.config.js

8.3 常用配置

javascript
// vite.config.js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': '/src'
    }
  },
  server: {
    port: 3000,
    proxy: {
      '/api': 'http://localhost:8080'
    }
  }
});

九、常见误区与最佳实践

误区一:Vue 3 完全兼容 Vue 2

虽然核心思想一致,但 Vue 3 在响应式原理、生命周期、API 风格上有较大变化,迁移需要评估。

误区二:所有数据都用 reactive

reactive 有不能替换整个对象的限制。对于简单值和需要重新赋值的场景,用 ref 更合适。

误区三:v-for 用索引当 key

这是 Vue 开发中最常见的坑之一。key 应该是唯一且稳定的标识。

最佳实践

  1. 新项目优先使用 Vue 3 + Vite + TypeScript
  2. 使用 <script setup> 简化代码
  3. 按功能组织 Composition API 代码
  4. 状态管理优先选择 Pinia
  5. 路由使用 History 模式时注意服务器配置
  6. 长列表使用虚拟滚动

十、总结

Vue 以其渐进式和易用性赢得了大量开发者。Vue 2 的 Object.defineProperty 奠定了响应式基础,Vue 3 的 Proxy 则带来了更好的性能和更完整的响应式能力。理解虚拟 DOM、Diff 算法、Composition API、Vue Router、Pinia 和性能优化,能够帮助我们构建高质量的 Vue 应用。

九、Vue 的渲染机制

9.1 模板编译

Vue 的模板会被编译成渲染函数。编译过程包括:

  1. 解析模板生成 AST
  2. 对 AST 进行优化(标记静态节点)
  3. 生成渲染函数代码
javascript
// 模板
// <div>&#123;&#123; message &#125;&#125;</div>

// 编译后的渲染函数
function render(_ctx, _cache) {
  return _openBlock(), _createElementBlock('div', null, _toDisplayString(_ctx.message), 1 /* TEXT */);
}

9.2 静态节点提升

Vue 3 编译器会识别模板中的静态节点,在首次渲染后复用,减少不必要的 Diff。

十、Vue 的响应式系统细节

10.1 依赖收集

Vue 3 使用 effectdep 实现依赖收集:

  • 读取响应式数据时,当前 effect 被收集到 dep 中
  • 修改响应式数据时,dep 通知所有 effect 重新执行

10.2 ref 的自动解包

在模板中,ref 会自动解包,不需要写 .value

vue
<template>
  <div>&#123;&#123; count &#125;&#125;</div>
</template>

<script setup>
const count = ref(0);
</script>

10.3 reactive 的局限性

reactive 不能直接替换整个对象,否则响应式会丢失。

javascript
const state = reactive({ count: 0 });
state = { count: 1 }; // 错误!响应式丢失

十一、Vue Router 进阶

11.1 动态路由匹配

javascript
const routes = [
  { path: '/user/:id', component: User }
];

11.2 路由懒加载

javascript
const User = () => import('./views/User.vue');

11.3 导航守卫

javascript
router.beforeEach((to, from, next) => {
  // 权限校验
});

十二、Vue 与 TypeScript

12.1 <script setup> 与 TS

vue
<script setup lang="ts">
interface Props {
  title: string;
}
const props = defineProps<Props>();
</script>

12.2 类型推断

Vue 3 对 TypeScript 支持更好,ref、reactive、computed 都能正确推断类型。

十三、Vue 性能优化深入

13.1 v-memo

Vue 3.2 新增的 v-memo 可以缓存子树,只在依赖变化时更新。

vue
<div v-memo="[valueA, valueB]">
  <!-- 只有 valueA 或 valueB 变化时才重新渲染 -->
</div>

13.2 异步组件

vue
<script setup>
import { defineAsyncComponent } from 'vue';
const AsyncComp = defineAsyncComponent(() => import('./Heavy.vue'));
</script>

13.3 长列表优化

对于长列表,使用虚拟滚动库如 vue-virtual-scroller

十四、总结

Vue 以其优雅的设计和渐进式的特点,成为前端开发的主流选择之一。从 Vue 2 到 Vue 3,响应式原理从 Object.defineProperty 升级为 Proxy,Composition API 让复杂逻辑组织更清晰,Vite 让开发体验更上一层楼。掌握 Vue 的核心原理和实践技巧,能够帮助我们构建高性能、可维护的前端应用。

十五、Vue 的自定义指令

15.1 什么是指令

Vue 提供了内置指令如 v-ifv-forv-model。我们也可以注册自定义指令来封装 DOM 操作。

javascript
const vFocus = {
  mounted: (el) => el.focus()
};
vue
<input v-focus />

15.2 指令生命周期

  • created:绑定元素的属性或事件监听器之前
  • beforeMount:元素挂载前
  • mounted:元素挂载后
  • beforeUpdate:更新前
  • updated:更新后
  • beforeUnmount:卸载前
  • unmounted:卸载后

十六、Vue 的渲染函数与 JSX

16.1 渲染函数

Vue 支持用 h 函数直接写渲染函数。

javascript
import { h } from 'vue';

export default {
  render() {
    return h('div', { class: 'app' }, 'Hello');
  }
};

16.2 JSX

Vue 也支持 JSX,需要配置 @vitejs/plugin-vue-jsx

jsx
export default {
  render() {
    return <div class="app">Hello</div>;
  }
};

十七、Vue 的动画与过渡

17.1 Transition 组件

Vue 提供了 <Transition><TransitionGroup> 组件实现动画效果。

vue
<Transition name="fade">
  <p v-if="show">Hello</p>
</Transition>
css
.fade-enter-active, .fade-leave-active {
  transition: opacity 0.5s;
}
.fade-enter-from, .fade-leave-to {
  opacity: 0;
}

十八、Vue 的插件机制

18.1 编写插件

Vue 插件是一个对象或函数,必须暴露 install 方法。

javascript
const MyPlugin = {
  install(app, options) {
    app.config.globalProperties.$myMethod = () => {};
    app.provide('myKey', options);
  }
};

app.use(MyPlugin, { foo: 'bar' });

18.2 常用插件

  • Vue Router
  • Pinia
  • Vue I18n
  • Element Plus / Ant Design Vue

十九、Vue 项目的最佳实践

19.1 使用组合式函数

把可复用的逻辑封装成组合式函数(Composables)。

javascript
// composables/useMouse.js
import { ref, onMounted, onUnmounted } from 'vue';

export function useMouse() {
  const x = ref(0);
  const y = ref(0);
  const update = (e) => { x.value = e.pageX; y.value = e.pageY; };
  onMounted(() => window.addEventListener('mousemove', update));
  onUnmounted(() => window.removeEventListener('mousemove', update));
  return { x, y };
}

19.2 避免滥用 watch

watch 应该用于处理副作用,而不是替代 computed。

二十、总结

Vue 是一个设计优雅、生态丰富的前端框架。从响应式原理到虚拟 DOM,从 Options API 到 Composition API,从 Vue Router 到 Pinia,Vue 为开发者提供了完整而灵活的开发体验。掌握 Vue 的核心原理和最佳实践,结合实际项目经验,能够让我们开发出高质量的 Vue 应用。

二十一、Vue 的插槽机制

21.1 默认插槽

插槽让父组件可以向子组件传递内容。

vue
<!-- Child.vue -->
<template>
  <div>
    <slot>默认内容</slot>
  </div>
</template>
vue
<!-- Parent.vue -->
<Child>传入的内容</Child>

21.2 具名插槽

vue
<!-- Child.vue -->
<template>
  <header><slot name="header"></slot></header>
  <main><slot></slot></main>
</template>
vue
<!-- Parent.vue -->
<Child>
  <template #header>标题</template>
  <p>正文</p>
</Child>

21.3 作用域插槽

子组件可以向插槽传递数据,父组件通过作用域插槽接收。

vue
<!-- Child.vue -->
<slot :user="user"></slot>
vue
<!-- Parent.vue -->
<Child v-slot="{ user }">
  &#123;&#123; user.name &#125;&#125;
</Child>

二十二、Vue 的 Teleport

Teleport 可以把组件渲染到 DOM 的其他位置,类似于 React Portals。

vue
<Teleport to="body">
  <div class="modal">Modal content</div>
</Teleport>

二十三、Vue 的 Provide / Inject

23.1 跨层级传值

Provide / Inject 用于祖先组件向后代组件传递数据,避免 props 逐层传递。

vue
<script setup>
import { provide } from 'vue';
provide('user', { name: 'Tom' });
</script>
vue
<script setup>
import { inject } from 'vue';
const user = inject('user');
</script>

23.2 注意事项

Provide / Inject 适合低频更新的数据,如主题、语言、用户信息。高频数据建议使用 Pinia。

二十四、Vue 的 Suspense

Vue 3 也支持 Suspense,用于处理异步组件或异步依赖。

vue
<Suspense>
  <template #default>
    <AsyncComponent />
  </template>
  <template #fallback>
    <div>Loading...</div>
  </template>
</Suspense>

二十五、Vue 与微前端

25.1 Vue 在微前端中的应用

Vue 应用可以通过 qiankun、MicroApp 等微前端框架集成到更大的系统中。

25.2 注意样式隔离

微前端场景下要注意 CSS 隔离,避免子应用之间样式冲突。

二十六、Vue 的生态系统

Vue 的生态系统非常丰富:

  • Vue Router:路由管理
  • Pinia:状态管理
  • Vite:构建工具
  • Nuxt:全栈框架
  • Element Plus / Ant Design Vue:UI 组件库
  • VueUse:常用组合式函数库

二十七、总结

Vue 是一个既优雅又强大的前端框架。无论是小型项目还是大型企业应用,Vue 都能提供合适的解决方案。理解响应式原理、虚拟 DOM、Composition API、路由、状态管理和性能优化,是成为 Vue 高级工程师的必经之路。随着 Vue 生态的不断发展,我们有理由相信 Vue 会在前端领域继续保持重要地位。

二十七、Vue 性能优化进阶

27.1 避免不必要的响应式转换

对于不需要响应式的数据,使用 markRawshallowRef

javascript
import { markRaw } from 'vue';
const largeList = markRaw([/* 大量数据 */]);

27.2 组件懒加载

javascript
const Heavy = defineAsyncComponent(() => import('./Heavy.vue'));

27.3 路由懒加载与代码分割

Vue Router 结合 Vite 的动态导入,可以实现路由级别的代码分割。

javascript
const routes = [
  {
    path: '/about',
    component: () => import('./views/About.vue')
  }
];

二十八、Vue 与测试

28.1 单元测试

使用 Vue Test Utils 和 Vitest 测试组件。

javascript
import { mount } from '@vue/test-utils';
import Counter from './Counter.vue';

 test('increments counter', async () => {
  const wrapper = mount(Counter);
  await wrapper.find('button').trigger('click');
  expect(wrapper.text()).toContain('1');
});

28.2 E2E 测试

使用 Cypress 或 Playwright 进行端到端测试。

二十九、Vue 的 SSR 与 Nuxt

29.1 Nuxt 框架

Nuxt 是 Vue 生态中的全栈框架,提供 SSR、SSG、文件路由、API 路由等功能。

29.2 服务端渲染优势

  • 更好的首屏性能
  • 更好的 SEO
  • 更好的社交分享预览

三十、总结

Vue 的学习是一个由浅入深的过程。从基础的模板语法到复杂的响应式原理,从 Options API 到 Composition API,从单页面应用到 SSR,Vue 为开发者提供了丰富的能力。希望本文能够帮助你系统地理解 Vue,在实际开发中写出高质量、高性能的 Vue 应用。

三十一、Vue 与 TypeScript 进阶

31.1 泛型组件

Vue 3 支持泛型组件,提高组件的复用性和类型安全。

vue
<script setup lang="ts" generic="T extends { id: number }">
const props = defineProps<{
  items: T[];
}>();
</script>

31.2 类型安全的 Pinia

Pinia 与 TypeScript 结合可以提供完整的类型推断。

typescript
export const useStore = defineStore('main', () => {
  const count = ref(0);
  return { count };
});

三十二、Vue 的生态系统扩展

32.1 VueUse

VueUse 提供了大量实用的组合式函数,如 useMouseuseLocalStorageuseDark 等。

32.2 Nuxt 模块

Nuxt 拥有丰富的模块生态,可以快速添加 PWA、SEO、数据库等功能。

三十三、Vue 项目中的状态管理选择

33.1 局部状态

组件内部状态使用 refreactive

33.2 跨组件状态

小范围跨组件状态使用 Provide/Inject 或事件总线。

33.3 全局状态

中大型应用使用 Pinia 管理全局状态。

三十四、总结

Vue 是一个值得深入学习的框架。它的设计兼顾了简洁性和强大功能,无论是新手还是资深开发者都能从中受益。通过本文的学习,希望你对 Vue 的核心原理和实践有了更全面的认识,能够在项目中灵活运用这些知识。

三十五、Vue 的响应式调试技巧

35.1 Vue DevTools

Vue DevTools 是调试 Vue 应用的利器,可以查看组件树、状态、事件和性能。

35.2 打印响应式对象

直接打印响应式对象可能看到 Proxy 包装。可以使用 toRaw 获取原始对象。

javascript
import { toRaw } from 'vue';
console.log(toRaw(state));

35.3 watchEffect 调试

watchEffect 会自动追踪依赖,适合需要响应多个数据源的场景。

javascript
import { watchEffect } from 'vue';
watchEffect(() => {
  console.log(count.value, user.value.name);
});

三十六、Vue 的国际化

36.1 Vue I18n

Vue I18n 是 Vue 生态中最流行的国际化方案。

javascript
import { createI18n } from 'vue-i18n';

const i18n = createI18n({
  locale: 'zh',
  messages: {
    zh: { hello: '你好' },
    en: { hello: 'Hello' }
  }
});
vue
<template>
  <p>&#123;&#123; $t('hello') &#125;&#125;</p>
</template>

三十七、Vue 与动画

37.1 列表过渡

使用 <TransitionGroup> 为列表添加进入和离开动画。

vue
<TransitionGroup name="list" tag="ul">
  <li v-for="item in list" :key="item.id">&#123;&#123; item.name &#125;&#125;</li>
</TransitionGroup>

37.2 第三方动画库

Vue 可以与 GSAP、Framer Motion 等动画库结合使用,实现复杂动画效果。

三十九、Vue 3.4+ 新特性

39.1 defineModel:简化双向绑定

Vue 3.4 引入了更简洁的 defineModel,替代了之前需要 defineProps + defineEmitsv-model 实现。

vue
<!-- Child.vue -->
<script setup>
const modelValue = defineModel();
</script>

<template>
  <input v-model="modelValue" />
</template>

父组件:

vue
<Child v-model="parentValue" />

生活化比喻:defineModel 像一条双向车道,props 和 emits 以前需要分两座桥走,现在一座桥就能双向通行。

39.2 v-bind 同名简写

Vue 3.4 支持 v-bind 同名简写:

vue
<!-- 之前 -->
<Child :title="title" :user="user" />

<!-- Vue 3.4+ -->
<Child :title :user />

39.3 更高效的响应式系统

Vue 3.4 对响应式系统做了多项优化:

  • 计算属性(computed)的重新计算更高效。
  • watchEffect 的清理逻辑更可靠。
  • 内存占用和初始化性能都有所改善。

39.4 全局组件类型推断改进

Vue 3.3+ 对泛型组件和全局组件的类型推断不断增强,Vue 3.4 进一步减少了 TypeScript 类型错误和 any 的使用。


四十、Vapor Mode:Vue 的性能新方向

40.1 什么是 Vapor Mode?

Vapor Mode 是 Vue 团队正在开发的全新编译策略,目标是生成更轻量、运行更快、内存占用更少的代码。它放弃了虚拟 DOM,转而编译为更细粒度的 DOM 操作指令。

生活化比喻:传统虚拟 DOM 像先用 Photoshop 画好设计稿,再按图施工;Vapor Mode 像经验丰富的老师傅直接在现场精准施工,省去“画稿”这一步。

40.2 Vapor Mode 的特点

特性传统 Vue 3Vapor Mode
运行时虚拟 DOM + Diff编译时生成 DOM 操作
包体积较大更小
内存占用中等更低
更新性能优秀更优秀(特定场景)
兼容性完整逐步支持

40.3 如何使用 Vapor Mode?

Vapor Mode 目前处于实验阶段,未来可能会通过编译器选项开启:

js
// vite.config.js
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";

export default defineConfig({
  plugins: [
    vue({
      vapor: true // 实验性配置
    })
  ]
});

40.4 对开发者的意义

  • 不需要修改业务代码,即可享受性能提升。
  • 将进一步缩小 Vue 与原生 JS / Svelte 等无虚拟 DOM 方案在性能上的差距。
  • 是 Vue 编译器演进的重要方向,值得关注。

四十一、Vue Router Data Loaders:路由级数据加载

41.1 为什么需要 Data Loaders?

在大型 Vue 应用中,数据获取通常分散在组件的 onMounted、路由守卫或状态管理中。这种分散导致:

  • 数据加载逻辑和路由耦合不清晰。
  • 导航等待体验难以统一控制。
  • SSR 场景下数据预取困难。

Vue Router Data Loaders 提供了一种声明式、路由级别的数据加载方案。

41.2 基本用法

js
import { defineLoader } from "vue-router";

export const useUserData = defineLoader(async (route) => {
  const response = await fetch(`/api/users/${route.params.id}`);
  if (!response.ok) throw new Error("User not found");
  return response.json();
});

组件中使用:

vue
<script setup>
import { useUserData } from "./loaders";

const { data, error, isLoading } = useUserData();
</script>

<template>
  <div v-if="isLoading">加载中...</div>
  <div v-else-if="error">出错了:&#123;&#123; error.message &#125;&#125;</div>
  <div v-else>&#123;&#123; data.name &#125;&#125;</div>
</template>

41.3 Data Loaders 的优势

  • 路由级数据管理:数据加载逻辑集中管理,组件更纯粹。
  • 导航守卫集成:可以在导航前加载数据,统一处理 loading/error。
  • SSR 友好:服务端可以预取数据,提升首屏性能。
  • 类型安全:与 TypeScript 配合良好。

41.4 与 Pinia / 组件内数据获取的对比

方案适用场景
组件内 onMounted + fetch简单页面、局部数据
Pinia Store全局状态、跨组件共享
Vue Router Data Loaders路由进入时必须加载的数据

四十二、总结

Vue 是一个兼具优雅与实力的前端框架。通过本文的学习,我们了解了 Vue 的响应式原理、虚拟 DOM、Composition API、路由、状态管理、性能优化以及工程实践,并深入探讨了 Vue 3.4+ 新特性、Vapor Mode 和 Vue Router Data Loaders。Vue 3.4 让双向绑定和组件通信更简洁,Vapor Mode 代表了编译器性能优化的未来方向,而 Data Loaders 则为路由级数据管理提供了更优雅的方案。希望这些知识能够帮助你在 Vue 开发中更加得心应手,构建出优秀的前端应用。


领域编号:E07 Vue 原理与生态
最后更新:2026-06-24


本领域学习进度

学习进度0 / 43 (0%)

基于 MIT 协议发布