docs: clarify optional page drivers in page guide

Update documentation to show that simple pages can define page models
directly in views without creating a page driver. Adjust examples,
section numbering, and naming guidance to better distinguish simple view
state from reusable page-driver patterns.docs: clarify optional page drivers in page guide

Update documentation to show that simple pages can define page models
directly in views without creating a page driver. Adjust examples,
section numbering, and naming guidance to better distinguish simple view
state from reusable page-driver patterns.
This commit is contained in:
skytek_xinliang
2026-05-27 11:18:19 +08:00
parent b8664b5c3e
commit ad00f5c195
8 changed files with 59 additions and 232 deletions
+30 -52
View File
@@ -7,18 +7,22 @@
目前新增一般頁面的預設資料流:
```txt
router -> view -> page driver -> page component -> sections/items
router -> view -> (page driver) -> page component -> sections/items
store/composable -> service
store/composable -> service
```
## 1. 新增 page driver
Page driver 不是必備層:若頁面邏輯只有簡單的 `computed` page model(無搜尋、無 dialog、無複雜事件協調),直接在 view 裡寫即可,不需要建立 page driver
頁面資料、事件與暫時 UI state 優先放在 page driverview 只負責掛載。
## 1. 新增 view(含 page model
```ts
// src/composables/page-drivers/useReportsPage.ts
簡單頁面的 page model 直接在 view 裡用 `computed` 組裝,不需要額外建立 page driver。
```vue
<!-- src/views/reports/Reports.vue -->
<script setup lang="ts">
import { computed, ref } from 'vue'
import PageReports from '@/components/pages/PageReports.vue'
import { useSnackbarStore } from '@/stores/snackbar'
export interface ReportSummary {
@@ -27,37 +31,29 @@ export interface ReportSummary {
owner: string
}
export interface ReportsPageModel {
title: string
rows: ReportSummary[]
}
const initialRows: ReportSummary[] = [
{ id: 1, title: '學生統計', owner: '教務處' },
{ id: 2, title: '課程統計', owner: '課務組' },
]
export function useReportsPage() {
const snackbar = useSnackbarStore()
const rows = ref<ReportSummary[]>(initialRows)
const snackbar = useSnackbarStore()
const rows = ref<ReportSummary[]>(initialRows)
const pageModel = computed(() => ({
title: '報表清單',
rows: rows.value,
}))
const pageModel = computed<ReportsPageModel>(() => ({
title: '報表清單',
rows: rows.value,
}))
function openReport(row: ReportSummary) {
snackbar.show({ message: `開啟:${row.title}`, color: 'info' })
}
return {
pageModel,
openReport,
}
function openReport(row: ReportSummary) {
snackbar.show({ message: `開啟:${row.title}`, color: 'info' })
}
</script>
<template>
<PageReports :page="pageModel" @open="openReport" />
</template>
```
資料來自 APIpage driver 可呼叫 store 或 composable;底層 HTTP 細節仍放在 `services/modules/*`
頁面需要協調多個 composable(搜尋、表單、CRUD flow、dialog 狀態),才建立 page driver。page driver 的慣例見 `src/composables/GUIDE.md`
## 2. 新增 page component
@@ -66,10 +62,10 @@ export function useReportsPage() {
```vue
<!-- src/components/pages/PageReports.vue -->
<script setup lang="ts">
import type { ReportSummary, ReportsPageModel } from '@/composables/page-drivers/useReportsPage'
import type { ReportSummary } from '@/views/reports/Reports.vue'
defineProps<{
page: ReportsPageModel
page: { title: string; rows: ReportSummary[] }
}>()
const emit = defineEmits<{
@@ -106,25 +102,7 @@ const emit = defineEmits<{
若畫面是固定的「篩選條件 + 查詢按鈕 + 結果表格」,優先使用 `components/sections/SectionQueryPage.vue`。若是「表單欄位 + 送出/存檔按鈕」,優先使用 `components/sections/SectionFormPage.vue`
## 3. 新增 route view
view 維持薄層,只呼叫 page driver 並掛載 page component。
```vue
<!-- src/views/reports/Reports.vue -->
<script setup lang="ts">
import PageReports from '@/components/pages/PageReports.vue'
import { useReportsPage } from '@/composables/page-drivers/useReportsPage'
const page = useReportsPage()
</script>
<template>
<PageReports :page="page.pageModel.value" @open="page.openReport" />
</template>
```
## 4. 加入 route
## 3. 加入 route
route 加在 `src/router/routes.ts``routes` 陣列中,並放在 `/:pathMatch(.*)*` catch-all route 前面。
@@ -147,7 +125,7 @@ route 加在 `src/router/routes.ts` 的 `routes` 陣列中,並放在 `/:pathMa
- 新功能若使用後端選單,優先調整後端選單資料或對應 API mock,不要把頁面專屬選單邏輯塞進 layout。
- 若只是新增 route,通常不需要修改 `MainLayout.vue``src/shell/*`
## 5. 需要 API 時新增 service module
## 4. 需要 API 時新增 service module
```ts
// src/services/modules/reports.ts
@@ -170,7 +148,7 @@ service 只封裝 HTTP 細節,不持有 UI 狀態。
`httpClient``baseURL` 來自 `VITE_API_BASE_URL`,沒有設定時預設 `/service/api`。開發模式下,Vite proxy 會將 `/service/*` 轉送到 `VITE_PROXY_TARGET`
## 6. 需要共享狀態時新增 store
## 5. 需要共享狀態時新增 store
只有跨頁共享、需要快取、或全域狀態才新增 store。單頁暫時狀態留在 view、component 或 composable。
@@ -202,7 +180,7 @@ export const useReportsStore = defineStore('reports', () => {
})
```
## 7. 驗證
## 6. 驗證
至少執行: