前端工程化 - 看起来“很合理”的feature目录结构
看起来“很合理”的feature目录结构
src/
├─ feature/
│ └─ Order/
│ ├─ index.vue
│ ├─ components/
│ │ ├─ OrderTable.vue
│ │ ├─ FilterForm.vue
│ │ ├─ AdvancedFilter.vue
│ │ ├─ ExportButton.vue
│ │ ├─ StatusSelect.vue
│ │ └─ OrderDetailDialog.vue
│ ├─ hooks/
│ │ ├─ useOrder.ts
│ │ └─ usePermission.ts
│ ├─ api.ts
│ └─ utils.ts
<template>
<div class="order-page">
<FilterForm
:filters="filters"
@change="onFilterChange"
/>
<AdvancedFilter
v-if="showAdvanced"
:filters="filters"
@change="onAdvancedChange"
/>
<div class="actions">
<ExportButton
:orders="orderList"
:permission="permission"
/>
<StatusSelect
:selected="selectedOrders"
@change="onStatusChange"
/>
</div>
<OrderTable
:data="orderList"
@row-click="openDetail"
/>
<OrderDetailDialog
v-if="showDetail"
:order-id="currentOrderId"
@close="showDetail = false"
/>
</div>
</template>
<script setup lang="ts">
import FilterForm from './components/FilterForm.vue'
import AdvancedFilter from './components/AdvancedFilter.vue'
import ExportButton from './components/ExportButton.vue'
import StatusSelect from './components/StatusSelect.vue'
import OrderTable from './components/OrderTable.vue'
import OrderDetailDialog from './components/OrderDetailDialog.vue'
import { useOrder } from './hooks/useOrder'
import { usePermission } from './hooks/usePermission'
const {
orderList,
filters,
fetchOrders,
onFilterChange,
onAdvancedChange,
selectedOrders,
onStatusChange,
openDetail,
showDetail,
currentOrderId
} = useOrder()
const permission = usePermission()
</script>
表面看:
- 目录清晰
- 按类型拆
- 每个东西都有地方放
👉 但这是一个“工程灾难的温床”。
错误1:
一个业务需求会横跨所有目录
如: 高级筛选条件变更,同时影响导出逻辑
在这个目录结构下,需要改:
components/AdvancedFilter.tsxservices/orderApi.tshooks/useOrder.tscomponents/ExportButton.tsx
一个需求,改4个层级,而不是一个业务单元
边界不是按类型,而是按变化
错误2:
所有能力默认都是同级的
在这个结构里
- 订单列表
- 导出
- 状态变更
- 高级筛选
在结构上是完全平级的,但是在业务上,他们的重要性完全不同
后果:
- 所有组件都在首屏被 import
- 所有逻辑都会进主 bundle
- lazy 很难加(因为到处有依赖)
技术上”lazy”,业务上完全不”lazy”
错误3:
通常这个面会这么写:
const OrderPage = lazy(() => import('./pages/OrderPage'))
然后会说:
我们已经做了懒加载了
但在orderPage 的chunk里:
- OrderTable
- AdvancedFilter
- ExportButton
- OrderDetailModal
- 所有 hooks
- 所有 api
这不是拆分,这是延迟加载一坨代码
错误4:
业务逻辑 被UI吸走了
典型现象:
<!-- ExportButton.vue -->
<script setup>
if (permission.canExport && filters.status === 'completed') {
enableExport.value = true
}
</script>
<!-- StatusSelect.vue -->
<script setup>
if (userRole === 'admin') {
allowChange.value = true
}
</script>
权限,规则散落在各个组件
后果:
- 改规则 = 全页面搜 if
- 新人不敢动
- 测试成本爆炸
这是边界彻底失效的信号
错误5
hook 变成”上帝对象”
// useOrder.ts
export function useOrder() {
// 拉列表
// 权限判断
// 高级筛选逻辑
// 导出状态
// 详情弹窗控制
}
看似 “逻辑被抽出来了”
实际只是把混轮从组件挪到了hook
hook 不是边界, 只是函数形式的容器

浙公网安备 33010602011771号