Vue
渐进式前端框架,可从简单的页面增强逐步扩展到完整 SPA。Vue 3 基于 Proxy 的响应式系统自动追踪依赖,无需手动声明更新。
单文件组件(SFC)
.vue 文件将模板、逻辑、样式封装在一起:
<script setup>
import { ref, computed } from "vue"
const count = ref(0)
const double = computed(() => count.value * 2)
</script>
<template>
<button @click="count++">{{ count }} × 2 = {{ double }}</button>
</template>
<style scoped>
button { padding: 0.5rem 1rem; }
</style><script setup> 是 Composition API 的语法糖,变量和函数自动暴露给模板。
Composition API
Vue 3 推荐写法,逻辑按关注点组织,可复用为 Composable。
响应式原语
| API | 用途 |
|---|---|
ref(val) | 基本类型 / 对象的响应式引用,访问需 .value |
reactive(obj) | 对象的深层响应式代理,无需 .value |
computed(() => ...) | 派生值,自动缓存 |
watch(src, cb) | 监听特定值变化 |
watchEffect(fn) | 自动追踪依赖,立即执行 |
import { ref, reactive, computed, watch } from "vue"
const name = ref("Alice")
const user = reactive({ age: 25, role: "admin" })
const label = computed(() => `${name.value} (${user.role})`)
watch(name, (newVal, oldVal) => {
console.log(`${oldVal} → ${newVal}`)
})Composable(可复用逻辑)
// useFetch.js
import { ref } from "vue"
export function useFetch(url) {
const data = ref(null)
const loading = ref(true)
fetch(url).then(r => r.json()).then(d => {
data.value = d
loading.value = false
})
return { data, loading }
}<script setup>
import { useFetch } from "./useFetch"
const { data, loading } = useFetch("/api/posts")
</script>Options API(Vue 2 风格)
仍然支持,适合小型组件或从 Vue 2 迁移:
export default {
data() { return { count: 0 } },
computed: {
double() { return this.count * 2 }
},
methods: {
inc() { this.count++ }
}
}组件通信
| 方式 | 方向 | 场景 |
|---|---|---|
props / emit | 父 ↔ 子 | 直接父子 |
provide / inject | 祖先 → 后代 | 跨层级传递 |
| Pinia | 全局 | 跨组件共享状态 |
v-model | 父 ↔ 子双向 | 表单控件封装 |
<!-- 父组件 -->
<Child :title="msg" @update="msg = $event" />
<!-- 子组件 -->
<script setup>
const props = defineProps({ title: String })
const emit = defineEmits(["update"])
</script>状态管理:Pinia
Vue 3 官方推荐,取代 Vuex:
// stores/counter.js
import { defineStore } from "pinia"
import { ref } from "vue"
export const useCounterStore = defineStore("counter", () => {
const count = ref(0)
const inc = () => count.value++
return { count, inc }
})<script setup>
import { useCounterStore } from "@/stores/counter"
const store = useCounterStore()
</script>
<template>
<button @click="store.inc">{{ store.count }}</button>
</template>模板指令速查
| 指令 | 作用 |
|---|---|
v-bind:prop / :prop | 动态绑定属性 |
v-on:click / @click | 事件监听 |
v-model | 双向绑定 |
v-if / v-else-if / v-else | 条件渲染 |
v-show | 切换 display(保留 DOM) |
v-for="item in list" | 列表渲染 |
v-slot | 具名插槽 |
生态
| 分类 | 工具 |
|---|---|
| 构建 | Vite(官方推荐) |
| 全栈框架 | Nuxt 3(SSR/SSG) |
| 路由 | Vue Router 4 |
| 状态管理 | Pinia |
| UI 组件库 | Element Plus、Naive UI、Vuetify |
| 测试 | Vitest + Vue Test Utils |
Vue 3 vs Vue 2
| 维度 | Vue 2 | Vue 3 |
|---|---|---|
| 响应式 | Object.defineProperty(有限制) | Proxy(深层、数组完整支持) |
| API 风格 | Options API | Composition API(+ Options 兼容) |
| TypeScript | 弱支持 | 原生支持 |
| 性能 | — | 更快的 diff、Tree-shaking |
| 状态管理 | Vuex | Pinia |
Vue vs React
| 维度 | Vue | React |
|---|---|---|
| 模板 | HTML 模板 + 指令,接近原生 | JSX,JS 中写 HTML |
| 响应式 | 自动追踪,无需手动声明依赖 | 需显式 setState / Hooks 规则 |
| 学习曲线 | 平缓,文档友好 | 较陡(理解 Hooks 规则) |
| 官方配套 | Router + Pinia 官方维护 | 社区选择多,无官方推荐 |
| 生态体量 | 稍小 | 更大(React Native) |