Vue3 组件设计模式与代码复用实践

发布于2026-09-02 14:25 阅读22次 讲解 Vue3 组件设计中的代码复用方案,对比组合式函数(Composables)、插槽(Slot)、混入(Mixin)、无渲染组件等模式的适用场景,用案例演示如何避免重复代码。
# Vue3 组件设计模式与代码复用实践
> 项目中重复代码越来越多?那是组件复用设计没做好。本文对比 Vue3 的几种代码复用手段,帮你选对方案。
## 一、复用的四种武器
- **组合式函数**:逻辑复用,复杂度低,首选方案
- **插槽 Slot**:结构复用,复杂度中
- **组件封装**:功能复用,复杂度低
- **Mixin**:传统方案,不推荐新项目使用
> 新版组合式函数 + 插槽可以覆盖 90% 的场景,Mixin 不推荐。
## 二、组合式函数(首选)
### 场景:多个组件都要请求列表 + 分页
```js
// composables/useList.js
export function useList(fetcher) {
const list = ref([]);
const loading = ref(false);
const page = ref(1);
async function load() {
loading.value = true;
try {
list.value = await fetcher(page.value);
} finally {
loading.value = false;
}
}
return { list, loading, page, load };
}
```
```vue
<script setup>
import { useList } from "./composables/useList";
const { list, loading, load } = useList((p) =>
api.getUsers({ page: p })
);
load();
</script>
```
> 逻辑抽成函数,任何组件都能用,测试也方便。
## 三、插槽(结构复用)
### 场景:不同页面的弹窗外观不同
```vue
<template>
<div class="modal">
<header><slot name="header">默认标题</slot></header>
<main><slot>默认内容</slot></main>
<footer><slot name="footer" /></footer>
</div>
</template>
```
```vue
<!-- 使用:传入不同内容 -->
<BaseModal>
<template #header>删除确认</template>
<p>确定要删除这条记录吗?</p>
<template #footer>
<button @click="cancel">取消</button>
<button class="danger" @click="del">删除</button>
</template>
</BaseModal>
```
## 四、作用域插槽(数据由子组件提供)
```vue
<List :items="users">
<template #item="{ item }">
<UserCard :user="item" />
</template>
</List>
```
## 五、Mixin 为什么不推荐
```js
// 旧方案:Mixin
const mixin = {
data() { return { count: 0 } },
methods: { inc() { this.count++ } }
};
```
问题:
- 属性来源不清晰,不知道哪个 mixin 提供的
- 多个 mixin 命名冲突难以排查
- TypeScript 支持差
> 组合式函数是 Mixin 的替代方案,逻辑来源一目了然。
## 六、无渲染组件(高级)
```js
// 只提供逻辑,不渲染任何 DOM
export default {
setup(props, { slots }) {
const state = reactive({ x: 0, y: 0 });
return () => slots.default({ state });
}
}
```
> 复杂场景再用,一般场景用组合式函数足够。
## 七、选型建议
- 纯逻辑复用 → **组合式函数**
- UI 结构复用 → **组件 + 插槽**
- 需要自定义渲染细节 → **作用域插槽**
- 老项目改造 → 逐步迁移到组合式函数
先想清楚复用的是逻辑还是结构,再选方案,代码自然清爽。