多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE

技术文章

聚焦一线编程技术原理与实战踩坑,沉淀可复用的工程经验。

Vue3 组合式 API 实战指南

Vue3 组合式 API 实战指南

Vue3 的组合式 API(Composition API)是 Vue 近几年最重要的演进。它解决了 Options API 在大型组件中"逻辑按选项分散、难以聚合"的痛点,让相关逻辑可以集中组织、抽离复用。本文覆盖 setup、响应式原理、计算属性、侦听器与生命周期,并演示如何抽离可复用逻辑。

一、setup:组合式 API 的入口

setup 是组合式 API 的入口函数,在组件创建之初执行,此时 props 已解析但尚未挂载 this。<script setup> 是它的语法糖,让代码更简洁,是 Vue3 的推荐写法。

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

// 响应式状态
const count = ref(0)
const double = computed(() => count.value * 2)

function add() {
  count.value++
}
</script>

<template>
  <button @click="add">{{ count }} × 2 = {{ double }}</button>
</template>

<script setup> 中,顶层声明的变量、函数会自动暴露给模板,无需 return,导入的组件也可直接使用。

二、ref 与 reactive:响应式双兄弟

ref 用于基本类型(也可包对象),通过 .value 访问;reactive 用于对象/数组,返回代理对象,直接访问属性即可。

import { ref, reactive } from 'vue'

// ref:基本类型推荐
const title = ref('多彩编程')
function setTitle(v) { title.value = v }

// reactive:对象/数组推荐
const user = reactive({
  name: '小明',
  age: 18,
  hobbies: ['编程', '阅读']
})
user.age++           // 直接修改
user.hobbies.push('音乐')

选择建议:基本类型用 ref,对象/集合用 reactive。解构 reactive 会丢失响应式,需要用 toRefs 保持;ref 解构则正常。

三、computed:派生状态

计算属性基于响应式依赖缓存,只有依赖变化时才重新计算,适合派生数据。

import { ref, computed } from 'vue'

const price = ref(100)
const qty = ref(3)

// 只读计算属性
const total = computed(() => price.value * qty.value)

// 可写计算属性(get/set)
const discount = computed({
  get: () => price.value * 0.8,
  set: (v) => { price.value = v / 0.8 }
})

四、watch 与 watchEffect:侦听变化

watch 显式指定侦听源,变化时执行回调,可拿到新旧值;watchEffect 自动收集回调内的依赖,立即执行一次,适合"副作用跟随依赖"的场景。

import { ref, watch, watchEffect } from 'vue'

const keyword = ref('')

// watch:明确侦听 keyword,变化时触发
watch(keyword, (newVal, oldVal) => {
  console.log(`${oldVal} -> ${newVal}`)
  fetchSuggest(newVal)
}, { immediate: false, deep: false })

// watchEffect:自动追踪回调内用到的响应式数据
watchEffect(() => {
  // 用到 keyword.value,自动建立依赖
  document.title = `搜索:${keyword.value}`
})
  • immediate: true 让 watch 立即执行一次。
  • deep: true 深度侦听对象内部变化(性能开销大,慎用)。
  • 侦听多个源:watch([a, b], ([na, nb]) => {})

五、生命周期:onMounted 等

组合式 API 把生命周期钩子改成函数形式,需在 setup 同步注册。

import { onMounted, onUpdated, onUnmounted } from 'vue'

onMounted(() => {
  console.log('DOM 已挂载,可访问 ref')
  window.addEventListener('resize', onResize)
})

onUnmounted(() => {
  // 组件销毁时清理,避免内存泄漏
  window.removeEventListener('resize', onResize)
})

六、实战:抽离可复用逻辑(Composable)

组合式 API 最大的价值在于把逻辑抽成独立函数复用。下面封装一个鼠标位置追踪逻辑,任何组件都能用。

// composables/useMousePosition.js
import { ref, onMounted, onUnmounted } from 'vue'

export function useMousePosition() {
  const x = ref(0)
  const y = ref(0)

  function update(e) {
    x.value = e.pageX
    y.value = e.pageY
  }

  onMounted(() => window.addEventListener('mousemove', update))
  onUnmounted(() => window.removeEventListener('mousemove', update))

  return { x, y }
}

// 组件中使用
// <script setup>
import { useMousePosition } from '@/composables/useMousePosition'
const { x, y } = useMousePosition()
// </script>
// <template>鼠标:{{ x }}, {{ y }}</template>

相比 Vue2 的 mixin,这种 Composable 模式有三大优势:

  • 来源清晰:逻辑来源一目了然,不再有 mixin 的隐式注入冲突。
  • 类型友好:配合 TypeScript 可获得完整类型推断。
  • 按需引入:像引入普通函数一样组合,灵活度极高。

掌握组合式 API 的关键,是建立"按功能而非按选项组织代码"的思维。当你在写一个复杂表单时,把校验逻辑、提交逻辑、字段联动各自抽成 Composable,组件会变得异常清爽。这正是组合式 API 带来的工程价值。

返回列表