最轻量且符合 Vue 3 设计哲学的逻辑拆分方式是按功能职责封装为独立组合式函数,统一置于 composables/ 目录,组件中解构调用;每个函数聚焦单一业务动作,返回明确状态与方法,兼顾内聚性与可复用性,并配合 defineProps/defineEmits 显式声明接口。

直接按功能职责拆成独立的组合式函数(Composable),放进 composables/ 目录,再在组件中解构调用——这是最轻量、最符合 Vue 3 设计哲学的拆分方式。
按业务功能切分逻辑,每个函数只做一件事
别把表单校验、接口请求、提示弹窗、权限判断全堆在 setup 里。识别出清晰的功能边界,比如:
- useLoginForm():管理输入值、规则、提交行为、错误状态
- useApiRequest():封装 loading、error、retry、取消请求等通用能力
- usePermission():读取角色、判断按钮是否显示、跳转是否允许
- useFileUpload():处理拖拽、预览、切片、进度、失败重试
每个函数返回明确的状态(ref/reactive)和方法(function),调用时解构即用,语义清晰,不耦合。
抽成可复用的 .js 文件,统一放在 composables/ 下
新建 src/composables/ 目录,每个函数一个文件,例如 useSearch.js:
立即学习“前端免费学习笔记(深入)”;
<!-- useSearch.js -->
import { ref, watch } from 'vue'
export function useSearch(fetchFn) {
const keyword = ref('')
const results = ref([])
const loading = ref(false)
watch(keyword, async (val) => {
if (!val?.trim()) return
loading.value = true
results.value = await fetchFn(val)
loading.value = false
})
return { keyword, results, loading }
}
组件内直接导入使用:
审查 Vue 管理后台的变更请求(Vue 2 + Element UI,Vue 3 + Element Plus)。重点关注最小化变更实现、上线风险检查以及回归检查清单生成。
<script setup>
import { useSearch } from '@/composables/useSearch'
import { searchApi } from '@/api'
const { keyword, results, loading } = useSearch(searchApi)
</script>
避免为拆而拆,守住内聚性底线
不是越细越好。关键看两点:
- 两个状态或方法是否总是一起变化、一起使用?比如
page和pageSize就该共存于usePagination() - 这个逻辑能否脱离当前组件,在其他地方独立复用?如果只能在这个页面用,暂时不必抽离
过度拆分反而增加跳转成本和理解负担,优先保证“一个函数 = 一个可解释的业务动作”。
配合 defineProps / defineEmits 显式声明接口
拆分后,组件对外的契约更关键。不要依赖运行时推断:
<script setup>
const props = defineProps({
userId: { type: String, required: true },
editable: Boolean
})
const emit = defineEmits(['update', 'delete'])
defineOptions({ name: 'UserProfileCard' })
// 后续调用 useUser(), useForm() 等...
</script>
这样调试时能看到准确的组件名,IDE 能精准提示 props 类型,团队协作也更可靠。

















