Skip to content
Vue.js 概述
1. 概述
前端开发中,直接操作 DOM 的方式在交互简单时足够直观。一旦页面状态分散、交互增多,查询和更新代码往往会高度耦合,维护代价随规模上升。
框架的演进方向之一,是将状态从 DOM 操作中剥离出来,让开发者描述数据与界面之间的关系,由框架负责视图更新。
Vue.js(发音 /vjuː/,类似 view)是一个用于构建用户界面的渐进式 JavaScript 框架。它由 Evan You 在 2013 年前后开始开发,设计上吸收了 Angular 的模板思想和 React 的响应式理念,同时刻意保持轻量、低侵入。
Vue 的核心可以概括为两个部分:声明式渲染和响应性。开发者使用模板语法描述界面长什么样,Vue 在数据变化时自动计算最小的 DOM 更新。
2. 基本概念
2.1 渐进式框架
Vue 的内核只处理视图层。路由、状态管理、构建工具等都可以按需集成,不会强制接管整个项目。
同样使用 Vue,可以只在现有页面中嵌入一小段交互:
html
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const { createApp } = Vue
createApp({
data() {
return { message: 'Hello Vue!' }
}
}).mount('#app')
</script>不需要构建步骤,一个 <script> 标签就能运行。
如果需要构建完整的单页应用(SPA),可以引入 Vue Router 管理前端路由,Pinia 做状态管理,Vite 负责开发和打包。对于重视 SEO 或首屏速度的场景,还可以使用服务端渲染(SSR)或静态站点生成(SSG),Nuxt 就是围绕这些场景建立的。
无论使用哪种方式,Vue 的核心 API 是一致的,变化的只是工程化程度。这种“用多少取多少”的设计也降低了后续重构或迁移的成本。
2.2 响应式数据
Vue 的响应式基于数据读写拦截。Vue 3 使用 ES6 Proxy;Vue 2 则依赖 Object.defineProperty,存在无法检测属性添加/删除的限制。
组件渲染函数第一次执行时,Vue 会记录哪些响应式数据被读取。这些数据一旦变化,就重新触发相关渲染或副作用。
js
import { reactive, watchEffect } from 'vue'
const state = reactive({ count: 0 })
watchEffect(() => {
console.log(`count is: ${state.count}`)
})
state.count++ // 控制台立刻输出 'count is: 1'reactive 将普通对象转为响应式代理,watchEffect 在其回调首次执行时收集到 state.count 的读取。随后 count 的改变会精确地触发该回调重新运行。
依赖追踪是细粒度的——改动一个属性不会导致整个组件树重新执行,只会影响真正依赖它的计算和渲染。不过,如果响应式对象在模板深层结构中被大量读取,依赖图并不会自动变得平坦,渲染范围的规划仍然值得留意。
2.3 声明式渲染
声明式描述的是“界面应该是什么样”,而不是“如何去修改 DOM”。对比下面两种方式:
js
// 命令式
const counterEl = document.getElementById('counter')
let count = 0
counterEl.textContent = count
button.addEventListener('click', () => {
count++
counterEl.textContent = count
})html
<!-- 声明式(Vue 模板) -->
<div id="app">
<button @click="count++">+1</button>
</div>js
createApp({
data() {
return { count: 0 }
}
}).mount('#app')声明式代码不需要手动调用 DOM 更新方法。数据变化后 Vue 自动更新视图,省去了条件显示、列表渲染等场景中的状态同步代码。
2.4 组件化
当界面规模变大,整个页面放在一个模板里很快就会失控。组件将 UI 拆分成独立的小块——导航栏、评论卡片、筛选栏——每个块都包含自己的模板、逻辑和样式。
Vue 的每个组件都是一个组件实例,拥有自己的响应式数据、计算属性和生命周期。父子组件之间通过 props 向下传递数据,通过事件向上通信,数据流保持单向。
单文件组件(.vue 文件)是这种模式最典型的载体:
vue
<script>
export default {
data() {
return { count: 0 }
}
}
</script>
<template>
<div>
<button @click="count++">+1</button>
</div>
</template>
<style scoped>
button {
font-weight: bold;
}
</style>一个文件封装了 HTML、JavaScript、CSS。scoped 属性会将样式作用域限制在当前组件,避免污染全局。这种封装有利于维护,多人协作时修改一个组件不易意外影响其他部分。
2.5 模板语法与指令
Vue 的模板语法是标准 HTML 的超集。插值表达式 {{ }} 用于输出文本,指令是以 v- 开头的特殊属性,用来将数据绑定到 DOM 行为。
常用基本形态:
v-bind(缩写:)绑定 attribute:<img :src="imageSrc" />v-on(缩写@)监听事件:<button @click="handleClick">v-if/v-show条件显示v-for列表渲染:<li v-for="item in items" :key="item.id">{{ item.name }}</li>
模板中可以直接访问 data 返回的属性,以及 computed、methods 上暴露的值。Vue 在编译阶段会将模板转换成渲染函数。
模板内只能使用单个表达式,语句不允许:
html
<!-- 正确:单个表达式 -->
<p>{{ isReady ? 'YES' : 'NO' }}</p>
<!-- 错误:这是语句,不是表达式 -->
<p>{{ if (isReady) { return 'YES' } else { return 'NO' } }}</p>这个限制是有意为之:复杂逻辑应该抽到计算属性或方法中,模板本身保持可读。
3. 基本用法
一个最简单的 Vue 应用只需创建一个应用实例并挂载:
js
createApp({
data() {
return { count: 0 }
}
}).mount('#app')createApp 返回应用实例,mount 将其挂载到指定的 DOM 元素上,Vue 会接管该元素内部的渲染。这种方式可以直接通过 <script> 标签引入 Vue 使用。
在工程化开发中,通常会借助构建工具使用单文件组件。推荐使用 npm create vue@latest 初始化项目,它会引导配置 TypeScript、Vue Router、Pinia 等模块。
4. 示例:计数器
完整单文件组件示例(选项式 API):
vue
<template>
<div>
<h1>计数器</h1>
<button @click="increment">加 1</button>
</div>
</template>
<script>
export default {
data() {
return {
count: 0
}
},
methods: {
increment() {
this.count++
}
}
}
</script>点击按钮后,count 递增。响应式系统检测到变化,重新执行组件的渲染函数,计算虚拟 DOM 差异并应用到真实 DOM,界面随之更新。整个过程开发者只变更了数据。
5. 注意点
- Vue 2 已于 2023 年 12 月 31 日停止维护,当前文档均针对 Vue 3。从 Vue 2 升级时可参考官方迁移指南。
- Vue 3 的响应式基于 Proxy,不支持 IE11。对旧浏览器的兼容需求需要评估。
- 组件的
data选项必须是一个函数,返回独立数据对象,以保证每个实例持有自己的数据副本。 - 模板内只允许单个表达式,复杂逻辑应当提取到
computed或methods中。 - 不推荐在同一元素上同时使用
v-if和v-for。Vue 3 中v-if优先级更高,如果需要先过滤再渲染列表,建议在计算属性中完成过滤,或通过外层容器处理。
6. 生态与应用
几个官方维护的库构成了常见组合:
- Vite:利用浏览器原生 ES 模块的开发服务器和打包工具,冷启动快,热模块替换(HMR)高效。
- Vue Router:官方路由库,管理 SPA 的页面导航和深层链接。
- Pinia:推荐的状态管理库,用于跨组件、跨页面的全局状态(如用户信息、购物车)。
- VueUse:组合式 API 工具函数集合,涵盖防抖、本地存储、元素尺寸观测等常用能力。
这些工具并不强制绑定,选择某个工具不要求必须使用其他工具。渐进式的理念同样延伸到了生态层面。
Vue 可以构建 SPA、SSR、SSG,也可以作为 Web Components 嵌入任意页面,甚至可以用于桌面端、移动端和命令行终端的界面开发。不论哪种形式,核心知识都是一致的。
7. 与其他框架的比较
Vue 经常被拿来与 React、Angular 一同讨论。三者在组件化和单向数据流上有重合,但存在明显差异。
- React:函数式倾向更明显,组件即函数,通过 hooks 管理状态。JSX 把渲染逻辑全部放在 JavaScript 中,自由度较高,但团队需要自行约定结构。响应式依赖需手动声明依赖数组。
- Angular:完整的平台型框架,自带 TypeScript、依赖注入、RxJS,结构严谨,适合大型企业应用,但学习成本较高。
- Vue:模板贴近 HTML,提供选项式和组合式两种 API 风格。响应式系统内置,开箱即用,不需要手动追踪依赖。在灵活性和上手门槛之间取了一个平衡点。
8. 学习路径
建议的入门顺序:
- 理解应用实例(
createApp)与根组件挂载。 - 熟悉模板语法:插值、指令、条件与循环。
- 深入组件系统:props、事件、插槽。
- 掌握响应式基础:
ref、reactive、计算属性。 - 根据项目类型选择性学习路由和状态管理。
