Vue

返回 JavaScript框架

渐进式前端框架,可从简单的页面增强逐步扩展到完整 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 2Vue 3
响应式Object.defineProperty(有限制)Proxy(深层、数组完整支持)
API 风格Options APIComposition API(+ Options 兼容)
TypeScript弱支持原生支持
性能更快的 diff、Tree-shaking
状态管理VuexPinia

Vue vs React

维度VueReact
模板HTML 模板 + 指令,接近原生JSX,JS 中写 HTML
响应式自动追踪,无需手动声明依赖需显式 setState / Hooks 规则
学习曲线平缓,文档友好较陡(理解 Hooks 规则)
官方配套Router + Pinia 官方维护社区选择多,无官方推荐
生态体量稍小更大(React Native)

ReactPreact