10.1 Composition API:按功能组织逻辑


文档摘要

10.1 Composition API:按功能组织逻辑 本节摘要:选项式 API 把一个功能的代码拆散到 data、methods、computed、watch 四处,功能一多就互相缠绕。Composition API 允许把一个关注点的数据、计算、侦听、方法写在一起,并抽成可复用的组合函数。本节覆盖 setup 语法、ref 与 reactive 的分工、生命周期对位,以及组合函数的抽取范式。 学习目标 阅读完本节,你应当能够: 用 script setup 写出等价于选项式的完整组件; 说清 ref 与 reactive 的取舍规则与解构陷阱的成因; 把一段业务逻辑抽成规范的组合函数; 判断什么逻辑值得抽、什么留在组件里。

10.1 Composition API:按功能组织逻辑

本节摘要:选项式 API 把一个功能的代码拆散到 data、methods、computed、watch 四处,功能一多就互相缠绕。Composition API 允许把一个关注点的数据、计算、侦听、方法写在一起,并抽成可复用的组合函数。本节覆盖 setup 语法、ref 与 reactive 的分工、生命周期对位,以及组合函数的抽取范式。

学习目标

阅读完本节,你应当能够:

  1. 用 script setup 写出等价于选项式的完整组件;
  2. 说清 ref 与 reactive 的取舍规则与解构陷阱的成因;
  3. 把一段业务逻辑抽成规范的组合函数;
  4. 判断什么逻辑值得抽、什么留在组件里。

一、选项式的痛:代码被类型撕碎

一个"搜索"功能,选项式下的代码散落四处:

export default { data() { return { keyword: '', results: [], loading: false // 搜索相关状态在这里 }; }, computed: { hasResult() { return this.results.length > 0; } // 搜索相关计算在这里 }, watch: { keyword(v) { this.do_search(v); } // 搜索相关侦听在这里 }, methods: { async do_search(v) { /* 搜索相关方法在这里 */ } } // 再加一个分页功能、一个筛选功能……四格里各自膨胀,读代码来回跳 };

组件超过两百行、功能超过三个,"找一个功能的完整实现"就开始翻页跳跃。选项式的分格按代码类型组织,而人的理解按功能组织——错位是结构性的,靠自觉克服不了。

二、组合式:同一功能的代码住在一起

<script setup> import { ref, computed, watch } from 'vue'; // ---- 搜索功能:状态 计算方法侦听 一屏之内 ---- const keyword = ref(''); const results = ref([]); const loading = ref(false); const hasResult = computed(() => results.value.length > 0); watch(keyword, (v) => do_search(v)); async function do_search(v) { loading.value = true; results.value = await api.search(v); loading.value = false; } // ---- 分页功能:紧跟其后 互不缠绕 ---- const page = ref(1); function next() { page.value++; } </script> <template> <input v-model="keyword"> <ul v-if="hasResult"><li v-for="r in results" :key="r.id">{{ r.title }}</li></ul> </template>

script setup 是编译期语法糖:顶层变量自动暴露给模板,组件导入即注册。this 消失了——这是有意为之,this 在选项式里是运行时绑定的黑盒,去掉后代码全是普通变量与函数,类型推导、按需引用、单元测试全部顺畅。

三、ref 与 reactive:分工与陷阱

const count = ref(0); // 基本值:必须用 ref 包进对象 const user = reactive({ name: '张三', age: 20 }); // 对象:可直接代理

ref 通过 value 属性读写(脚本里 count.value,模板里自动解包省掉 value),reactive 直接点取字段。分工建议明确化:基本值与需要整体替换的引用用 ref,结构数据组用 reactive;混着用容易出事,全 ref 也是一个自洽的流派——团队定一条即可。

reactive 有一个必须理解的陷阱:解构即失联

const { name } = user; // name 是普通字符串,与响应式断开 name = '李四'; // 视图不会更新 // 要保持响应式的解构,用工具函数 const { name: r_name } = toRefs(user); // 每个字段变成 ref,仍指向源

成因第 2 章讲过:Proxy 代理的是对象,解构取出的是值本身,离开代理对象就没人拦截读写了。参数传递同理——把 reactive 对象传给函数,函数内整体替换参数变量不会影响源。

四、生命周期对位

Vue 2 组合式(setup 内)
beforeCreate / created setup 本身(执行时机即取代这两者)
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
updated onUpdated
beforeDestroy / destroyed onBeforeUnmount / onUnmounted

created 没有对位函数,因为 setup 本身就在那个时机执行——组合式里"初始化逻辑"就是 setup 顶层代码。

五、组合函数:复用逻辑的单位

组件复用结构(插槽),组合函数复用逻辑。把上面的搜索抽出来:

// useSearch.js —— 一个规范的小组合函数 import { ref, computed } from 'vue'; export function useSearch(fetchFn, delay = 300) { const keyword = ref(''); const results = ref([]); const loading = ref(false); const hasResult = computed(() => results.value.length > 0); let timer = null; function on_input(v) { clearTimeout(timer); timer = setTimeout(() => do_search(v), delay); // 防抖内建 } async function do_search(v) { if (!v) { results.value = []; return; } loading.value = true; try { results.value = await fetchFn(v); } finally { loading.value = false; } } return { keyword, results, loading, hasResult, on_input }; }

任何组件两行接入:

const { keyword, results, loading, on_input } = useSearch(api.search);

规范要点:命名以 use 开头;入参收函数而非写死接口(可测试性);返回 ref 集合;副作用(定时器、监听)在函数内用生命周期钩子成对清理。它对比 Vue 2 时代混入(mixin)的优势是显式——来源看得见(import 语句)、命名冲突可解(解构重命名),混入那套"魔法注入、来源成谜、命名撞车"三大罪就此终结。

Options 与 Composition 组织方式对比

Options 与 Composition 组织方式对比

六、什么时候不必切组合式

组合式不是政治正确:几十行的小组件,选项式反而一眼可读;团队全是选项式存量、没有 TypeScript 计划,迁移收益有限。我的分界线:组件功能超过三个、或逻辑需要跨组件复用、或项目用 TypeScript——满足任一条就切,否则两种都合法。Vue 3 对两种风格是一等支持,不是替代关系。

本节要点回顾

  • 核心收益:按功能聚合取代按类型分格,大组件的可读性结构性改善;
  • ref/reactive 分工:基本值与整体替换用 ref,结构组用 reactive,解构断链用 toRefs 解;
  • this 消失:普通变量与函数换来类型推导与可测试性;
  • 组合函数规范:use 前缀、收函数入参、返回 ref、副作用成对清理,终结混入三罪;
  • 不必强切:小组件选项式依然顺手,按复杂度与复用需求决策。

组合函数还有一个隐性收益值得点破:它让"逻辑的边界"从组件里被拉出来,变成了可以被审视、被测试、被交接的独立单元。选项式时代,一段业务逻辑的完整行为分散在 data、methods、watch 里,交接时要读整个组件;组合函数时代,接手人看一个文件的输入输出就能复述行为。代码评审也因此有了更细的抓手——评审一个几十行的组合函数,比评审一个三百行的大组件容易做出实质性判断。这其实是本章所有语法变化的最终落点:写法的改变,服务于逻辑组织方式的改变。

写法升级之外,框架本身改了什么?下一节过 Vue 3 的特性与性能账本。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U