docs: 更新项目文档和经验教训总结
- 更新 CLAUDE.md:添加 2026-02-12 最新变更记录 - 更新 README.md:完善项目说明和最新更新内容 - 更新经验教训总结:新增 3 个重要实践案例 * 权限检查 Composable 模式 * 全局状态管理与页面生命周期协调 * 导航返回按钮与路由栈协调 记录了计划书模块、认证权限、消息功能等最佳实践 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Showing
3 changed files
with
352 additions
and
5 deletions
| ... | @@ -28,7 +28,7 @@ pnpm dev:tt # 字节跳动小程序开发 | ... | @@ -28,7 +28,7 @@ pnpm dev:tt # 字节跳动小程序开发 |
| 28 | 28 | ||
| 29 | ## 📋 快速参考 | 29 | ## 📋 快速参考 |
| 30 | 30 | ||
| 31 | -### 🆕 最新更新(2026-02) | 31 | +### 🆕 最新更新(2026-02-12) |
| 32 | 32 | ||
| 33 | **计划书功能优化**: | 33 | **计划书功能优化**: |
| 34 | - ✅ 添加计划书卡片状态标记("生成中"/"已完成",黄色/绿色背景) | 34 | - ✅ 添加计划书卡片状态标记("生成中"/"已完成",黄色/绿色背景) |
| ... | @@ -36,6 +36,23 @@ pnpm dev:tt # 字节跳动小程序开发 | ... | @@ -36,6 +36,23 @@ pnpm dev:tt # 字节跳动小程序开发 |
| 36 | - ✅ 优化页面滚动加载并清理调试代码 | 36 | - ✅ 优化页面滚动加载并清理调试代码 |
| 37 | - ✅ 修复搜索栏清空按钮点击无效 | 37 | - ✅ 修复搜索栏清空按钮点击无效 |
| 38 | - ✅ 修改提交结果页按钮为"返回上一页" | 38 | - ✅ 修改提交结果页按钮为"返回上一页" |
| 39 | +- ✅ 预览成功后才调用查看接口,避免预览失败也翻状态 | ||
| 40 | +- ✅ 优化计划书提交跳转体验:关闭弹框时清理已选产品 | ||
| 41 | +- ✅ 提取计划书提交回调逻辑为 composable | ||
| 42 | + | ||
| 43 | +**认证与权限优化**: | ||
| 44 | +- ✅ 为所有制作计划书按钮添加登录权限检查 | ||
| 45 | +- ✅ 修复退出登录时红点状态未重置的问题 | ||
| 46 | +- ✅ 修复登录页返回按钮:清空 router store 并跳转到首页 | ||
| 47 | +- ✅ 修复 401 重定向死循环和返回报错问题 | ||
| 48 | + | ||
| 49 | +**消息功能优化**: | ||
| 50 | +- ✅ 配置 TabBar 红点功能使用新的 unread_msg_count 字段 | ||
| 51 | +- ✅ 修复 TabBar 未读红点显示问题 | ||
| 52 | +- ✅ 优化消息列表卡片布局,提升信息可读性 | ||
| 53 | +- ✅ 增加未读消息红点提示 | ||
| 54 | +- ✅ 优化消息详情页布局,避免内容重复显示 | ||
| 55 | +- ✅ 添加消息列表 API 错误提示 | ||
| 39 | 56 | ||
| 40 | **样式改进**: | 57 | **样式改进**: |
| 41 | - ✅ 增强资料卡片边框可见性(border-gray-200) | 58 | - ✅ 增强资料卡片边框可见性(border-gray-200) |
| ... | @@ -46,12 +63,21 @@ pnpm dev:tt # 字节跳动小程序开发 | ... | @@ -46,12 +63,21 @@ pnpm dev:tt # 字节跳动小程序开发 |
| 46 | - ✅ 重构"我的"页面为专业高端风格 | 63 | - ✅ 重构"我的"页面为专业高端风格 |
| 47 | - ✅ 优化 ProductCard 组件视觉样式 | 64 | - ✅ 优化 ProductCard 组件视觉样式 |
| 48 | - ✅ 统一视觉柔和度和整体设计一致性 | 65 | - ✅ 统一视觉柔和度和整体设计一致性 |
| 66 | +- ✅ 优化首页头图 CDN 加载 | ||
| 49 | 67 | ||
| 50 | -**认证优化**: | 68 | +**计划书字段优化**: |
| 51 | -- ✅ 修复 401 重定向死循环和返回报错问题 | 69 | +- ✅ 优化提取金额字段并新增每年提取字段 |
| 70 | +- ✅ 隐藏产品详情页附件下载提示 | ||
| 71 | +- ✅ 优化输入框间距 | ||
| 52 | 72 | ||
| 53 | **代码质量**: | 73 | **代码质量**: |
| 54 | - ✅ 从版本控制中移除本地配置文件 settings.local.json | 74 | - ✅ 从版本控制中移除本地配置文件 settings.local.json |
| 75 | +- ✅ 禁用消息列表 Mock 数据,使用真实接口 | ||
| 76 | +- ✅ 清理调试日志 | ||
| 77 | + | ||
| 78 | +**API 集成进度**: | ||
| 79 | +- ✅ 总接口数:29,已完成:26 (89.7%) | ||
| 80 | +- ✅ 计划书模块接口联调完成(submitPlanAPI、listAPI) | ||
| 55 | 81 | ||
| 56 | **新增功能**: | 82 | **新增功能**: |
| 57 | - ✅ 消息列表和消息详情页 | 83 | - ✅ 消息列表和消息详情页 |
| ... | @@ -60,6 +86,7 @@ pnpm dev:tt # 字节跳动小程序开发 | ... | @@ -60,6 +86,7 @@ pnpm dev:tt # 字节跳动小程序开发 |
| 60 | - ✅ 分类列表页 | 86 | - ✅ 分类列表页 |
| 61 | - ✅ PlanFields 表单字段组件集 | 87 | - ✅ PlanFields 表单字段组件集 |
| 62 | - ✅ useCollectOperation composable | 88 | - ✅ useCollectOperation composable |
| 89 | +- ✅ usePlanPermission composable | ||
| 63 | 90 | ||
| 64 | --- | 91 | --- |
| 65 | 92 | ... | ... |
| ... | @@ -45,7 +45,7 @@ pnpm lint | ... | @@ -45,7 +45,7 @@ pnpm lint |
| 45 | - ✅ **组件复用** - "第 3 次出现原则"抽取 Composables | 45 | - ✅ **组件复用** - "第 3 次出现原则"抽取 Composables |
| 46 | - ✅ **可复用组件** - TabBar、NavHeader、IconFont | 46 | - ✅ **可复用组件** - TabBar、NavHeader、IconFont |
| 47 | 47 | ||
| 48 | -## 🆕 最新更新(2026-02) | 48 | +## 🆕 最新更新(2026-02-12) |
| 49 | 49 | ||
| 50 | ### 计划书功能优化 | 50 | ### 计划书功能优化 |
| 51 | - ✅ **状态标记** - 添加计划书卡片状态标记("生成中" / "已完成") | 51 | - ✅ **状态标记** - 添加计划书卡片状态标记("生成中" / "已完成") |
| ... | @@ -54,16 +54,38 @@ pnpm lint | ... | @@ -54,16 +54,38 @@ pnpm lint |
| 54 | - 使用条件类名动态切换样式 | 54 | - 使用条件类名动态切换样式 |
| 55 | - ✅ **查看状态更新** - 仅在预览成功后标记为已查看,返回列表不刷新位置 | 55 | - ✅ **查看状态更新** - 仅在预览成功后标记为已查看,返回列表不刷新位置 |
| 56 | - ✅ **提交跳转体验** - 提交后先关闭并重置弹框,再无固定延迟跳转结果页 | 56 | - ✅ **提交跳转体验** - 提交后先关闭并重置弹框,再无固定延迟跳转结果页 |
| 57 | -- ✅ **返回重置体验** - 结果页返回后表单不保留旧数据 | 57 | +- ✅ **返回重置体验** - 关闭弹框时清理已选产品,确保返回后表单为空 |
| 58 | +- ✅ **字段优化** - 优化提取金额字段并新增每年提取字段 | ||
| 59 | + | ||
| 60 | +### 认证与权限优化 | ||
| 61 | +- ✅ **登录权限检查** - 为所有制作计划书按钮添加登录权限检查 | ||
| 62 | +- ✅ **红点状态管理** - 修复退出登录时红点状态未重置的问题 | ||
| 63 | +- ✅ **TabBar 红点** - 配置 TabBar 红点功能使用新的 unread_msg_count 字段 | ||
| 64 | +- ✅ **登录页返回** - 修复登录页返回按钮,清空 router store 并跳转到首页 | ||
| 65 | +- ✅ **401 修复** - 修复 401 重定向死循环和返回报错问题 | ||
| 66 | + | ||
| 67 | +### 消息功能优化 | ||
| 68 | +- ✅ **消息列表** - 优化消息列表卡片布局,提升信息可读性 | ||
| 69 | +- ✅ **消息详情** - 优化消息详情页布局,避免内容重复显示 | ||
| 70 | +- ✅ **未读提示** - 增加未读消息红点提示 | ||
| 71 | +- ✅ **API 错误处理** - 添加消息列表 API 错误提示 | ||
| 58 | 72 | ||
| 59 | ### 视觉优化 | 73 | ### 视觉优化 |
| 60 | - ✅ **首页网格导航** - 优化导航图标视觉体验 | 74 | - ✅ **首页网格导航** - 优化导航图标视觉体验 |
| 61 | - ✅ **产品卡片** - 优化 ProductCard 组件视觉样式 | 75 | - ✅ **产品卡片** - 优化 ProductCard 组件视觉样式 |
| 62 | - ✅ **页面风格** - 重构"我的"页面为专业高端风格 | 76 | - ✅ **页面风格** - 重构"我的"页面为专业高端风格 |
| 63 | - ✅ **统一视觉** - 优化视觉柔和度和整体统一性 | 77 | - ✅ **统一视觉** - 优化视觉柔和度和整体统一性 |
| 78 | +- ✅ **头图优化** - 优化首页头图 CDN 加载 | ||
| 79 | + | ||
| 80 | +### API 集成 | ||
| 81 | +- ✅ **接口联调完成** - 计划书模块接口联调完成(submitPlanAPI、listAPI) | ||
| 82 | +- ✅ **总进度** - 29 个接口,已完成 26 个(89.7%) | ||
| 83 | +- ✅ **关闭 Mock** - 禁用消息列表 Mock 数据,使用真实接口 | ||
| 64 | 84 | ||
| 65 | ### 代码质量 | 85 | ### 代码质量 |
| 66 | - ✅ **移除本地配置** - 从版本控制中移除本地配置文件 settings.local.json | 86 | - ✅ **移除本地配置** - 从版本控制中移除本地配置文件 settings.local.json |
| 87 | +- ✅ **Composable 抽取** - 提取计划书提交回调逻辑为 composable | ||
| 88 | +- ✅ **清理调试日志** - 清理项目中的调试日志 | ||
| 67 | - ✅ **文档更新** - 完善开发文档和经验教训总结 | 89 | - ✅ **文档更新** - 完善开发文档和经验教训总结 |
| 68 | 90 | ||
| 69 | ## ⚡ 常见问题 | 91 | ## ⚡ 常见问题 | ... | ... |
| ... | @@ -1200,6 +1200,304 @@ const fetchList = async (params) => { | ... | @@ -1200,6 +1200,304 @@ const fetchList = async (params) => { |
| 1200 | } | 1200 | } |
| 1201 | ``` | 1201 | ``` |
| 1202 | 1202 | ||
| 1203 | +### ✅ 5. 权限检查 Composable 模式 ⭐ 2026-02-12 新增 | ||
| 1204 | + | ||
| 1205 | +**场景描述**: | ||
| 1206 | + | ||
| 1207 | +项目中需要在多个入口点(如首页、搜索页、产品中心页、产品详情页)添加"制作计划书"按钮的登录权限检查功能。 | ||
| 1208 | + | ||
| 1209 | +**问题**: | ||
| 1210 | +- 如果在每个页面都重复写权限检查逻辑,会导致代码重复 | ||
| 1211 | +- 权限逻辑分散在各个页面,难以统一维护 | ||
| 1212 | + | ||
| 1213 | +**解决方案:抽取为 Composable** | ||
| 1214 | + | ||
| 1215 | +创建 `src/composables/usePlanPermission.js`: | ||
| 1216 | + | ||
| 1217 | +```javascript | ||
| 1218 | +/** | ||
| 1219 | + * 计划书权限检查 Composable | ||
| 1220 | + * | ||
| 1221 | + * @description 检查用户是否已登录,未登录时引导用户登录 | ||
| 1222 | + * @returns {Object} { checkPlanPermission } 权限检查函数 | ||
| 1223 | + */ | ||
| 1224 | +import { useUserStore } from '@/stores/user' | ||
| 1225 | +import Taro from '@tarojs/taro' | ||
| 1226 | + | ||
| 1227 | +export function usePlanPermission() { | ||
| 1228 | + const userStore = useUserStore() | ||
| 1229 | + | ||
| 1230 | + /** | ||
| 1231 | + * 检查计划书权限 | ||
| 1232 | + * | ||
| 1233 | + * @param {Function} callback - 权限验证通过后的回调函数 | ||
| 1234 | + * @description 如果用户未登录,显示登录提示;否则执行回调函数 | ||
| 1235 | + */ | ||
| 1236 | + const checkPlanPermission = (callback) => { | ||
| 1237 | + console.log('[usePlanPermission] 检查登录状态:', userStore.isLoggedIn) | ||
| 1238 | + | ||
| 1239 | + if (!userStore.isLoggedIn) { | ||
| 1240 | + // 未登录:显示登录提示 | ||
| 1241 | + Taro.showModal({ | ||
| 1242 | + title: '提示', | ||
| 1243 | + content: '请先登录后再制作计划书', | ||
| 1244 | + confirmText: '去登录', | ||
| 1245 | + cancelText: '取消', | ||
| 1246 | + success: (res) => { | ||
| 1247 | + if (res.confirm) { | ||
| 1248 | + // 跳转到登录页 | ||
| 1249 | + Taro.navigateTo({ | ||
| 1250 | + url: '/pages/login/index' | ||
| 1251 | + }) | ||
| 1252 | + } | ||
| 1253 | + } | ||
| 1254 | + }) | ||
| 1255 | + } else { | ||
| 1256 | + // 已登录:执行回调函数 | ||
| 1257 | + callback?.() | ||
| 1258 | + } | ||
| 1259 | + } | ||
| 1260 | + | ||
| 1261 | + return { | ||
| 1262 | + checkPlanPermission | ||
| 1263 | + } | ||
| 1264 | +} | ||
| 1265 | +``` | ||
| 1266 | + | ||
| 1267 | +**使用方式**: | ||
| 1268 | + | ||
| 1269 | +```vue | ||
| 1270 | +<script setup> | ||
| 1271 | +import { usePlanPermission } from '@/composables/usePlanPermission' | ||
| 1272 | + | ||
| 1273 | +const { checkPlanPermission } = usePlanPermission() | ||
| 1274 | + | ||
| 1275 | +const handlePlanClick = () => { | ||
| 1276 | + checkPlanPermission(() => { | ||
| 1277 | + // 权限验证通过后的操作 | ||
| 1278 | + openPlanPopup() | ||
| 1279 | + }) | ||
| 1280 | +} | ||
| 1281 | +</script> | ||
| 1282 | + | ||
| 1283 | +<template> | ||
| 1284 | + <button @tap="handlePlanClick">制作计划书</button> | ||
| 1285 | +</template> | ||
| 1286 | +``` | ||
| 1287 | + | ||
| 1288 | +**收益**: | ||
| 1289 | +- ✅ 减少代码重复,统一权限检查逻辑 | ||
| 1290 | +- ✅ 易于维护:修改权限逻辑只需更新一处 | ||
| 1291 | +- ✅ 复用性强:任何需要权限检查的地方都可以使用 | ||
| 1292 | + | ||
| 1293 | +**适用场景**: | ||
| 1294 | +- 需要登录才能使用的功能 | ||
| 1295 | +- 需要特定权限才能访问的功能 | ||
| 1296 | +- 需要统一权限检查逻辑的场景 | ||
| 1297 | + | ||
| 1298 | +--- | ||
| 1299 | + | ||
| 1300 | +### ✅ 6. 全局状态管理与页面生命周期协调 ⭐ 2026-02-12 新增 | ||
| 1301 | + | ||
| 1302 | +**场景描述**: | ||
| 1303 | + | ||
| 1304 | +项目中需要管理 TabBar 红点的显示状态,红点数据来自用户信息接口返回的 `unread_msg_count` 字段。当用户退出登录时,需要清除红点状态。 | ||
| 1305 | + | ||
| 1306 | +**问题**: | ||
| 1307 | +- 红点状态存储在用户 store 中 | ||
| 1308 | +- 退出登录时需要重置红点状态 | ||
| 1309 | +- 登录后需要自动显示/隐藏红点 | ||
| 1310 | + | ||
| 1311 | +**解决方案:在登录/登出时管理红点状态** | ||
| 1312 | + | ||
| 1313 | +**1. 登录成功后显示红点**: | ||
| 1314 | + | ||
| 1315 | +```javascript | ||
| 1316 | +// src/pages/login/index.vue | ||
| 1317 | +const handleLogin = async () => { | ||
| 1318 | + try { | ||
| 1319 | + const res = await loginAPI({ phone, code }) | ||
| 1320 | + | ||
| 1321 | + if (res.code === 1) { | ||
| 1322 | + // 更新用户信息(包含 unread_msg_count) | ||
| 1323 | + userStore.setUserInfo(res.data.userInfo) | ||
| 1324 | + | ||
| 1325 | + // TabBar 会自动读取 userStore.unread_msg_count | ||
| 1326 | + // 如果大于 0,TabBar 组件会自动显示红点 | ||
| 1327 | + } | ||
| 1328 | + } catch (err) { | ||
| 1329 | + console.error('登录失败:', err) | ||
| 1330 | + } | ||
| 1331 | +} | ||
| 1332 | +``` | ||
| 1333 | + | ||
| 1334 | +**2. 退出登录时清除红点**: | ||
| 1335 | + | ||
| 1336 | +```javascript | ||
| 1337 | +// src/stores/user.js | ||
| 1338 | +export const useUserStore = defineStore('user', () => { | ||
| 1339 | + const userInfo = ref(null) | ||
| 1340 | + const unreadMsgCount = ref(0) // 红点数量 | ||
| 1341 | + | ||
| 1342 | + const setUserInfo = (info) => { | ||
| 1343 | + userInfo.value = info | ||
| 1344 | + // 从用户信息中提取未读消息数量 | ||
| 1345 | + unreadMsgCount.value = info.unread_msg_count || 0 | ||
| 1346 | + } | ||
| 1347 | + | ||
| 1348 | + const logout = () => { | ||
| 1349 | + userInfo.value = null | ||
| 1350 | + unreadMsgCount.value = 0 // 清除红点状态 ⚠️ 重要 | ||
| 1351 | + Taro.clearStorageSync() // 清除本地缓存 | ||
| 1352 | + } | ||
| 1353 | + | ||
| 1354 | + return { | ||
| 1355 | + userInfo, | ||
| 1356 | + unreadMsgCount, | ||
| 1357 | + setUserInfo, | ||
| 1358 | + logout | ||
| 1359 | + } | ||
| 1360 | +}) | ||
| 1361 | +``` | ||
| 1362 | + | ||
| 1363 | +**3. TabBar 组件读取红点状态**: | ||
| 1364 | + | ||
| 1365 | +```vue | ||
| 1366 | +<!-- src/components/TabBar.vue --> | ||
| 1367 | +<script setup> | ||
| 1368 | +import { useUserStore } from '@/stores/user' | ||
| 1369 | + | ||
| 1370 | +const userStore = useUserStore() | ||
| 1371 | +const hasUnread = computed(() => userStore.unreadMsgCount > 0) | ||
| 1372 | +</script> | ||
| 1373 | + | ||
| 1374 | +<template> | ||
| 1375 | + <view class="tabbar-item"> | ||
| 1376 | + <image :src="iconPath" /> | ||
| 1377 | + <view class="badge" v-if="hasUnread"></view> <!-- 红点 --> | ||
| 1378 | + </view> | ||
| 1379 | +</template> | ||
| 1380 | +``` | ||
| 1381 | + | ||
| 1382 | +**关键要点**: | ||
| 1383 | +1. ✅ **状态同步**:登录后从 `userInfo` 中提取 `unread_msg_count` | ||
| 1384 | +2. ✅ **状态清除**:退出登录时必须重置 `unreadMsgCount = 0` | ||
| 1385 | +3. ✅ **响应式更新**:使用 `computed` 自动响应状态变化 | ||
| 1386 | +4. ✅ **单一数据源**:红点状态只由 `userStore` 管理 | ||
| 1387 | + | ||
| 1388 | +**注意事项**: | ||
| 1389 | +- ⚠️ **必须在退出时清除状态**:否则下次登录会显示错误的红点 | ||
| 1390 | +- ⚠️ **字段名对齐**:确保后端返回字段名与前端一致(`unread_msg_count`) | ||
| 1391 | +- ⚠️ **类型转换**:如果后端返回字符串,需要转换为数字 | ||
| 1392 | + | ||
| 1393 | +--- | ||
| 1394 | + | ||
| 1395 | +### ✅ 7. 导航返回按钮与路由栈协调 ⭐ 2026-02-12 新增 | ||
| 1396 | + | ||
| 1397 | +**场景描述**: | ||
| 1398 | + | ||
| 1399 | +当用户从 401 错误被重定向到登录页后,点击返回按钮会出现问题,因为导航栈已被清空(`router store` 中存储的路径已丢失)。 | ||
| 1400 | + | ||
| 1401 | +**问题**: | ||
| 1402 | +- 401 重定向后,`router store` 被清空 | ||
| 1403 | +- 登录页点击返回按钮时,没有历史页面可以返回 | ||
| 1404 | +- 用户被困在登录页,无法返回首页 | ||
| 1405 | + | ||
| 1406 | +**解决方案 1:检测路由栈,为空时跳转首页** | ||
| 1407 | + | ||
| 1408 | +```vue | ||
| 1409 | +<!-- src/pages/login/index.vue --> | ||
| 1410 | +<script setup> | ||
| 1411 | +import { useRouterStore } from '@/stores/router' | ||
| 1412 | + | ||
| 1413 | +const routerStore = useRouterStore() | ||
| 1414 | + | ||
| 1415 | +const handleBack = () => { | ||
| 1416 | + // 检查路由栈是否有历史记录 | ||
| 1417 | + if (routerStore.history && routerStore.history.length > 0) { | ||
| 1418 | + // 有历史记录:正常返回 | ||
| 1419 | + Taro.navigateBack() | ||
| 1420 | + } else { | ||
| 1421 | + // 无历史记录:清空 router store 并跳转首页 | ||
| 1422 | + routerStore.clearHistory() // 清空路由栈 | ||
| 1423 | + Taro.switchTab({ | ||
| 1424 | + url: '/pages/index/index' | ||
| 1425 | + }) | ||
| 1426 | + } | ||
| 1427 | +} | ||
| 1428 | +</script> | ||
| 1429 | + | ||
| 1430 | +<template> | ||
| 1431 | + <NavHeader @back="handleBack" /> | ||
| 1432 | +</template> | ||
| 1433 | +``` | ||
| 1434 | + | ||
| 1435 | +**解决方案 2:NavHeader 组件提供 `preventDefaultBack` prop** | ||
| 1436 | + | ||
| 1437 | +```vue | ||
| 1438 | +<!-- src/components/navigation/NavHeader.vue --> | ||
| 1439 | +<script setup> | ||
| 1440 | +const props = defineProps({ | ||
| 1441 | + preventDefaultBack: { | ||
| 1442 | + type: Boolean, | ||
| 1443 | + default: false | ||
| 1444 | + } | ||
| 1445 | +}) | ||
| 1446 | + | ||
| 1447 | +const emit = defineEmits(['back']) | ||
| 1448 | + | ||
| 1449 | +const handleBack = () => { | ||
| 1450 | + if (props.preventDefaultBack) { | ||
| 1451 | + // 阻止默认返回,由父组件处理 | ||
| 1452 | + emit('back') | ||
| 1453 | + } else { | ||
| 1454 | + // 默认返回行为 | ||
| 1455 | + Taro.navigateBack() | ||
| 1456 | + } | ||
| 1457 | +} | ||
| 1458 | +</script> | ||
| 1459 | + | ||
| 1460 | +<template> | ||
| 1461 | + <view class="nav-header" @tap="handleBack"> | ||
| 1462 | + <image class="back-icon" src="/assets/images/back.png" /> | ||
| 1463 | + </view> | ||
| 1464 | +</template> | ||
| 1465 | +``` | ||
| 1466 | + | ||
| 1467 | +**在登录页使用**: | ||
| 1468 | + | ||
| 1469 | +```vue | ||
| 1470 | +<!-- src/pages/login/index.vue --> | ||
| 1471 | +<script setup> | ||
| 1472 | +import { useRouterStore } from '@/stores/router' | ||
| 1473 | + | ||
| 1474 | +const routerStore = useRouterStore() | ||
| 1475 | + | ||
| 1476 | +const handleBack = () => { | ||
| 1477 | + // 清空路由栈并跳转首页 | ||
| 1478 | + routerStore.clearHistory() | ||
| 1479 | + Taro.switchTab({ | ||
| 1480 | + url: '/pages/index/index' | ||
| 1481 | + }) | ||
| 1482 | +} | ||
| 1483 | +</script> | ||
| 1484 | + | ||
| 1485 | +<template> | ||
| 1486 | + <NavHeader :prevent-default-back="true" @back="handleBack" /> | ||
| 1487 | +</template> | ||
| 1488 | +``` | ||
| 1489 | + | ||
| 1490 | +**关键要点**: | ||
| 1491 | +1. ✅ **路由栈管理**:使用 `routerStore` 维护导航历史 | ||
| 1492 | +2. ✅ **状态检测**:检查路由栈是否有历史记录 | ||
| 1493 | +3. ✅ **降级方案**:无历史记录时,跳转到首页 | ||
| 1494 | +4. ✅ **组件通信**:通过 `@back` 事件和 `preventDefaultBack` prop 协调返回行为 | ||
| 1495 | + | ||
| 1496 | +**收益**: | ||
| 1497 | +- ✅ 避免用户被困在登录页 | ||
| 1498 | +- ✅ 提供更好的用户体验 | ||
| 1499 | +- ✅ 组件职责清晰,易于复用 | ||
| 1500 | + | ||
| 1203 | --- | 1501 | --- |
| 1204 | 1502 | ||
| 1205 | ## Vue 3 响应式数据和表单状态管理 | 1503 | ## Vue 3 响应式数据和表单状态管理 | ... | ... |
-
Please register or login to post a comment