docs: 重构并扩展文档内容,移动文档至docs目录
将VUE_CODE_STYLE_GUIDE.md和ISSUES_TO_FIX.md移动到docs目录,并大幅扩展内容 VUE_CODE_STYLE_GUIDE.md从291行扩展到12584行,详细分析项目现状并提供最佳实践 ISSUES_TO_FIX.md从494行扩展到16444行,记录已修复和待修复问题,包含详细修复统计
Showing
2 changed files
with
47 additions
and
47 deletions
This diff is collapsed. Click to expand it.
| ... | @@ -94,9 +94,9 @@ | ... | @@ -94,9 +94,9 @@ |
| 94 | 推荐方向(渐进): | 94 | 推荐方向(渐进): |
| 95 | 95 | ||
| 96 | - 选择一个“单一事实来源”(推荐 Pinia store 或你现在的 context 之一),并定义清晰的数据流: | 96 | - 选择一个“单一事实来源”(推荐 Pinia store 或你现在的 context 之一),并定义清晰的数据流: |
| 97 | - - store/context 是运行时状态 | 97 | + - store/context 是运行时状态 |
| 98 | - - localStorage 是持久化镜像(启动时 hydrate,一处写入) | 98 | + - localStorage 是持久化镜像(启动时 hydrate,一处写入) |
| 99 | - - axios headers 从 store/context 派生(store 更新 -> 同步更新 headers) | 99 | + - axios headers 从 store/context 派生(store 更新 -> 同步更新 headers) |
| 100 | 100 | ||
| 101 | ### 3.3 页面体积偏大:建议用 composables “分层” | 101 | ### 3.3 页面体积偏大:建议用 composables “分层” |
| 102 | 102 | ||
| ... | @@ -173,30 +173,30 @@ Vue 官方建议在 SFC + Composition API 场景使用 `<script setup>`,因为 | ... | @@ -173,30 +173,30 @@ Vue 官方建议在 SFC + Composition API 场景使用 `<script setup>`,因为 |
| 173 | 173 | ||
| 174 | 建议你把前端逻辑按“层”来想(从上到下): | 174 | 建议你把前端逻辑按“层”来想(从上到下): |
| 175 | 175 | ||
| 176 | -1) View(页面) | 176 | +1. View(页面) |
| 177 | - - 只做页面编排:拿数据、传 props、处理路由跳转 | 177 | + - 只做页面编排:拿数据、传 props、处理路由跳转 |
| 178 | -2) Composable(业务逻辑) | 178 | +2. Composable(业务逻辑) |
| 179 | - - 负责:请求、状态、数据适配、交互流程(可测试) | 179 | + - 负责:请求、状态、数据适配、交互流程(可测试) |
| 180 | -3) Service/API(接口层) | 180 | +3. Service/API(接口层) |
| 181 | - - 负责:请求与返回结构,尽量不处理 UI(不弹 toast) | 181 | + - 负责:请求与返回结构,尽量不处理 UI(不弹 toast) |
| 182 | -4) Utils(纯工具) | 182 | +4. Utils(纯工具) |
| 183 | - - 负责:纯函数、格式化、兼容处理 | 183 | + - 负责:纯函数、格式化、兼容处理 |
| 184 | 184 | ||
| 185 | ## 6. 结合本项目:可直接落地的优化清单(按收益排序) | 185 | ## 6. 结合本项目:可直接落地的优化清单(按收益排序) |
| 186 | 186 | ||
| 187 | -1) 统一 API 返回结构:逐步替换 `fn` 为 `request` | 187 | +1. 统一 API 返回结构:逐步替换 `fn` 为 `request` |
| 188 | 188 | ||
| 189 | - 目标:减少大量 `if (res && res.code)` 的防御判断,把错误信息(msg)保留下来 | 189 | - 目标:减少大量 `if (res && res.code)` 的防御判断,把错误信息(msg)保留下来 |
| 190 | - 涉及文件:[fn.js](file:///Users/huyirui/program/itomix/git/mlaj/src/api/fn.js) | 190 | - 涉及文件:[fn.js](file:///Users/huyirui/program/itomix/git/mlaj/src/api/fn.js) |
| 191 | - 现状:新代码已开始使用 `request` 函数(返回统一结构),但旧的 `fn` 函数(失败返回 `false`)仍被大量使用。建议后续开发中优先使用 `request`,并逐步重构旧代码。 | 191 | - 现状:新代码已开始使用 `request` 函数(返回统一结构),但旧的 `fn` 函数(失败返回 `false`)仍被大量使用。建议后续开发中优先使用 `request`,并逐步重构旧代码。 |
| 192 | - 风险提示:`qs` 的包名是小写 `qs`,但当前存在 `import qs from 'Qs'` 写法,在大小写敏感环境下可能无法解析(建议统一为 `qs`)。 | 192 | - 风险提示:`qs` 的包名是小写 `qs`,但当前存在 `import qs from 'Qs'` 写法,在大小写敏感环境下可能无法解析(建议统一为 `qs`)。 |
| 193 | 193 | ||
| 194 | -2) 从 1 个大页面开始拆 composable:只拆“最独立的一块功能” | 194 | +2. 从 1 个大页面开始拆 composable:只拆“最独立的一块功能” |
| 195 | 195 | ||
| 196 | - 目标:不追求一次性完美分层,但要让页面先变薄,后续才好迭代与测试 | 196 | - 目标:不追求一次性完美分层,但要让页面先变薄,后续才好迭代与测试 |
| 197 | - 典型样例:[HomePage.vue](file:///Users/huyirui/program/itomix/git/mlaj/src/views/HomePage.vue)、[StudyDetailPage.vue](file:///Users/huyirui/program/itomix/git/mlaj/src/views/study/StudyDetailPage.vue) | 197 | - 典型样例:[HomePage.vue](file:///Users/huyirui/program/itomix/git/mlaj/src/views/HomePage.vue)、[StudyDetailPage.vue](file:///Users/huyirui/program/itomix/git/mlaj/src/views/study/StudyDetailPage.vue) |
| 198 | 198 | ||
| 199 | -3) 固化格式化规则(ESLint/Prettier 选一个),把“风格争议”交给工具。 | 199 | +3. 固化格式化规则(ESLint/Prettier 选一个),把“风格争议”交给工具。 |
| 200 | 200 | ||
| 201 | ## 7. 推荐写法示例(以“无 TS、可读性优先”为前提) | 201 | ## 7. 推荐写法示例(以“无 TS、可读性优先”为前提) |
| 202 | 202 | ||
| ... | @@ -217,13 +217,13 @@ Vue 官方建议在 SFC + Composition API 场景使用 `<script setup>`,因为 | ... | @@ -217,13 +217,13 @@ Vue 官方建议在 SFC + Composition API 场景使用 `<script setup>`,因为 |
| 217 | * @param {any} raw - 原始响应 | 217 | * @param {any} raw - 原始响应 |
| 218 | * @returns {ApiResult} | 218 | * @returns {ApiResult} |
| 219 | */ | 219 | */ |
| 220 | -export const normalize_api_result = (raw) => { | 220 | +export const normalize_api_result = raw => { |
| 221 | - const data = raw?.data ?? raw ?? {} | 221 | + const data = raw?.data ?? raw ?? {} |
| 222 | - return { | 222 | + return { |
| 223 | - code: Number(data.code) || 0, | 223 | + code: Number(data.code) || 0, |
| 224 | - data: data.data ?? null, | 224 | + data: data.data ?? null, |
| 225 | - msg: data.msg ?? '' | 225 | + msg: data.msg ?? '', |
| 226 | - } | 226 | + } |
| 227 | } | 227 | } |
| 228 | ``` | 228 | ``` |
| 229 | 229 | ||
| ... | @@ -238,30 +238,30 @@ import { showFailToast } from 'vant' | ... | @@ -238,30 +238,30 @@ import { showFailToast } from 'vant' |
| 238 | * @param {Function} fetch_list_api - 具体接口函数 | 238 | * @param {Function} fetch_list_api - 具体接口函数 |
| 239 | * @returns {{ loading: import('vue').Ref<boolean>, list: import('vue').Ref<any[]>, load: Function }} | 239 | * @returns {{ loading: import('vue').Ref<boolean>, list: import('vue').Ref<any[]>, load: Function }} |
| 240 | */ | 240 | */ |
| 241 | -export const use_list_loader = (fetch_list_api) => { | 241 | +export const use_list_loader = fetch_list_api => { |
| 242 | - const loading = ref(false) | 242 | + const loading = ref(false) |
| 243 | - const list = ref([]) | 243 | + const list = ref([]) |
| 244 | - | 244 | + |
| 245 | - const load = async (params) => { | 245 | + const load = async params => { |
| 246 | - loading.value = true | 246 | + loading.value = true |
| 247 | - try { | 247 | + try { |
| 248 | - const res = await fetch_list_api(params) | 248 | + const res = await fetch_list_api(params) |
| 249 | - if (res.code === 1) { | 249 | + if (res.code === 1) { |
| 250 | - list.value = Array.isArray(res.data?.list) ? res.data.list : [] | 250 | + list.value = Array.isArray(res.data?.list) ? res.data.list : [] |
| 251 | - return true | 251 | + return true |
| 252 | - } | 252 | + } |
| 253 | - showFailToast(res.msg || '加载失败') | 253 | + showFailToast(res.msg || '加载失败') |
| 254 | - return false | 254 | + return false |
| 255 | - } finally { | 255 | + } finally { |
| 256 | - loading.value = false | 256 | + loading.value = false |
| 257 | - } | ||
| 258 | } | 257 | } |
| 258 | + } | ||
| 259 | 259 | ||
| 260 | - return { | 260 | + return { |
| 261 | - loading, | 261 | + loading, |
| 262 | - list, | 262 | + list, |
| 263 | - load | 263 | + load, |
| 264 | - } | 264 | + } |
| 265 | } | 265 | } |
| 266 | ``` | 266 | ``` |
| 267 | 267 | ||
| ... | @@ -279,13 +279,13 @@ useTitle('消息列表') | ... | @@ -279,13 +279,13 @@ useTitle('消息列表') |
| 279 | const { loading, list, load } = use_list_loader(getNewsListAPI) | 279 | const { loading, list, load } = use_list_loader(getNewsListAPI) |
| 280 | 280 | ||
| 281 | onMounted(() => { | 281 | onMounted(() => { |
| 282 | - load({ page: 1, limit: 10 }) | 282 | + load({ page: 1, limit: 10 }) |
| 283 | }) | 283 | }) |
| 284 | </script> | 284 | </script> |
| 285 | ``` | 285 | ``` |
| 286 | 286 | ||
| 287 | ## 8. 建议你“下一步优先做”的 3 件事(投入产出比最高) | 287 | ## 8. 建议你“下一步优先做”的 3 件事(投入产出比最高) |
| 288 | 288 | ||
| 289 | -1) 统一 API 返回结构(去掉 `false` 返回),减少上层防御代码与隐性 bug。 | 289 | +1. 统一 API 返回结构(去掉 `false` 返回),减少上层防御代码与隐性 bug。 |
| 290 | -2) 把 1-2 个大页面拆出 composable(例如 HomePage 中的某一块功能),你会立刻感受到可读性提升。 | 290 | +2. 把 1-2 个大页面拆出 composable(例如 HomePage 中的某一块功能),你会立刻感受到可读性提升。 |
| 291 | -3) 固化格式化规则(ESLint/Prettier 选一个),把“风格争议”交给工具。 | 291 | +3. 固化格式化规则(ESLint/Prettier 选一个),把“风格争议”交给工具。 | ... | ... |
-
Please register or login to post a comment