news 2026/4/19 7:14:23

第 28 课:任务页排序偏好与默认工作视图

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第 28 课:任务页排序偏好与默认工作视图

第 28 课:任务页排序偏好与默认工作视图

这一课,我们继续沿着任务管理页主线往下走,把它再往真实后台系统推进一步:

让用户不只是临时切换排序,还能把当前排序保存成“默认工作视图”。

这件事看起来只是多了一个“记住排序”的功能,但它背后其实牵涉一个很关键的前端设计问题:

  • 当前页面状态,应该怎么和 URL 协同?
  • 个人使用偏好,又应该放在哪里?
  • 当两者同时存在时,谁的优先级更高?

这一课一句话在做什么?

这一课我们完成了 6 件事:

  1. 给任务页增加“默认排序偏好”本地持久化。
  2. 让用户可以把“当前排序”保存成默认工作视图。
  3. 让用户可以一键恢复系统默认排序。
  4. 让任务页在 URL 没有显式sort参数时,自动恢复用户自己的默认排序。
  5. 继续保持“真实当前视图”同步到 URL。
  6. 补上单元测试、查询同步测试、E2E 和文档。

这一课最重要的设计结论

这一课最重要的不是按钮本身,而是下面这条优先级规则:

显式 URL sort > localStorage 默认工作视图 > 系统默认排序

为什么这样设计?

1. URL 里的 sort 是“当前场景状态”

如果用户现在访问的是:

  • /tasks?sort=dueDateDesc

那就说明这次访问已经明确指定了当前视图应该怎么排。

这种状态的特点是:

  • 可以刷新恢复
  • 可以分享给别人
  • 可以被浏览器前进后退保留

所以它的优先级应该最高。


2. localStorage 里的默认排序是“个人习惯”

如果用户平时习惯先看:

  • 截止日期从远到近

那这是一种个人使用偏好。

这种状态的特点是:

  • 更像“我的默认打开方式”
  • 不一定要分享给别人
  • 更适合保存在本机

所以它应该放进localStorage,而不是直接当成全局业务状态。


3. 系统默认排序只是兜底规则

如果:

  • URL 没给sort
  • 用户也没保存过默认工作视图

这时候才回退到系统默认排序,也就是:

  • default

这一课在useTasksPage里做了什么?

文件:

  • src/composables/useTasksPage.ts

这一课的核心仍然放在任务页组合式函数里,因为:

  • 当前排序是页面状态
  • 默认排序偏好也是页面级用户偏好
  • 它们都不适合散落到多个组件里各自管理

新增了默认排序持久化能力

这一课新增了本地存储 key:

  • TASK_TABLE_DEFAULT_SORT_STORAGE_KEY

同时补了几类辅助函数:

  • 排序合法性判断
  • 排序标准化函数
  • 默认排序读取函数
  • 默认排序写回函数
  • 排序值转中文文案函数

这说明我们已经开始在项目里重复练一种很重要的工程模式:

读取本地偏好 -> 做合法性清理 -> 写回标准化结果 -> 暴露给页面使用


把“当前排序”和“默认排序偏好”拆成了两份状态

这是这一课最关键的一点。

现在任务页里有两份排序相关状态:

  • sortOption
  • defaultSortOption

它们不是一回事。

sortOption

表示:

  • 当前这一次页面访问实际使用的排序方式
defaultSortOption

表示:

  • 用户希望以后直接打开任务页时优先使用的默认排序

这两份状态拆开以后,逻辑会清晰很多:

  • 你可以临时切换当前排序
  • 也可以决定要不要把它保存成默认工作视图
  • 还可以恢复系统默认

而不会把“当前场景状态”和“个人长期偏好”混成一份状态。


新增了几个更有业务语义的计算状态

例如:

  • currentSortOptionLabel
  • defaultSortOptionLabel
  • isCurrentSortSavedAsDefault
  • hasCustomizedDefaultSort

这些状态的意义不是“为了少写几行模板”,而是:

  • 让界面层更容易表达业务语义
  • 让消息提示更清楚
  • 让按钮显隐和禁用规则更直接

新增了两个真正有业务意图的动作函数

例如:

  • saveCurrentSortAsDefaultView()
  • resetDefaultSortPreference()

这两个函数很值得你注意。

因为它们不再是简单的“修改某个 ref”,而是在表达明确的业务动作:

  • 把当前排序保存成默认工作视图
  • 恢复系统默认排序

这就是组合式函数越来越像“页面领域层”的表现。


这一课在 URL 同步层做了什么?

文件:

  • src/composables/useTaskFilterQuerySync.ts

这一课最关键的升级是:

sort 的默认回退值,不再被硬编码成 'default'。

现在它会变成:

  • 先读 URL 里的sort
  • 如果 URL 没有合法sort
  • 就回退到defaultSortOption

这一步非常重要,因为它真正把:

  • URL 当前场景状态
  • localStorage 默认工作视图

接到一起了。


为什么 URL 里最终还是要写回 sort?

这里很多初学者会疑惑:

  • 既然默认排序来自 localStorage,为什么还要把它重新同步到 URL?

答案是:

因为一旦它已经成为“当前真实页面视图”,那它就不再只是一个隐形偏好,而是:

  • 当前页面真正生效的状态

所以它应该被同步进 URL,这样才具备:

  • 刷新恢复
  • 链接分享
  • 浏览器历史记录一致性

这也是这一课最值得建立的心智模型之一:

localStorage 可以决定初始值,但当前真实页面状态仍然应该由 URL 明确表达。


这一课在界面层做了什么?

文件:

  • src/components/tasks/TaskFilterBar.vue
  • src/views/TasksView.vue

这一课在排序下拉框下面补了一块“默认工作视图”说明区。

它做了三件事:

  1. 展示当前默认排序是什么。
  2. 告诉你当前排序是否已经保存成默认工作视图。
  3. 提供“设为默认视图”和“恢复系统默认”按钮。

这里要重点理解一个分层原则:

  • TaskFilterBar只负责展示和抛出事件
  • TasksView负责消息提示
  • useTasksPage负责真正的状态和持久化逻辑

这和我们前面反复练习的分层方式是一致的。


这一课补了哪些测试?

1.useTasksPage.spec.ts

新增覆盖:

  • 默认排序偏好恢复
  • 非法默认排序清理
  • 保存默认工作视图
  • 恢复系统默认排序
  • 当前排序状态与默认偏好状态分离

2.useTaskFilterQuerySync.spec.ts

新增覆盖:

  • URL 没有sort时,使用本地默认排序
  • 显式sort查询参数覆盖本地默认偏好
  • 非法sort查询参数回退到本地默认排序

这一层测试非常关键,因为这一课最容易出问题的地方其实不是按钮,而是:

  • URL 和本地偏好的优先级

3.e2e/app.spec.ts

新增覆盖:

  • 先切换排序
  • 再保存默认工作视图
  • 重新进入不带查询参数的/tasks
  • 断言默认排序被自动恢复
  • 再恢复系统默认
  • 再次进入干净任务页地址
  • 断言页面回到系统默认顺序

这能验证真正浏览器里最完整的一条用户路径。


这一课改了哪些文件?

  • src/composables/useTasksPage.ts
  • src/composables/useTaskFilterQuerySync.ts
  • src/components/tasks/TaskFilterBar.vue
  • src/views/TasksView.vue
  • src/composables/__tests__/useTasksPage.spec.ts
  • src/composables/__tests__/useTaskFilterQuerySync.spec.ts
  • e2e/pages/TasksPage.ts
  • e2e/app.spec.ts
  • docs/28-task-sort-preference-and-default-view.md
  • docs/README.md

这一课最值得你真正学会什么?

如果你只记住“多了一个默认排序按钮”,那还不够。

你更应该记住下面这 6 点:

  1. 当前页面状态和个人默认偏好,往往不是同一份状态。
  2. URL 更适合表达当前真实场景,本地存储更适合表达个人长期习惯。
  3. 当两者同时存在时,一定要提前定义清楚优先级。
  4. localStorage 里的值不能直接信任,读取后一定要标准化。
  5. 一个本地偏好一旦真正生效成当前页面视图,就应该同步回 URL。
  6. 这种“状态分层 + 优先级规则”的能力,一定要同时用单元测试和 E2E 验证。

这一课的验证结果

这一课相关改动完成后,应至少通过:

  • npm run test:unit -- --run
  • npm run type-check
  • npm run lint
  • npm run test:e2e -- --project=chromium
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/19 7:13:19

My Notes Keeper(个人数据管理软件)

链接:https://pan.quark.cn/s/08235799a24aMy Notes Keeper是一款小巧但功能齐全的个人数据管理软件。它类似于myBase和eDiary,但操作上更像Microsoft Word,即便对初次使用者来说,也能在几分钟内快速掌握。用户友好:操…

作者头像 李华
网站建设 2026/4/19 7:11:06

手把手教你用lite-avatar形象库:快速为数字人项目找到完美“脸”

手把手教你用lite-avatar形象库:快速为数字人项目找到完美"脸" 1. 为什么需要lite-avatar形象库? 开发数字人项目时,最让人头疼的环节之一就是寻找合适的虚拟形象。传统方案要么需要从零开始训练模型,耗费大量时间和算…

作者头像 李华
网站建设 2026/4/19 7:10:27

Whisper-large-v3在医疗领域的应用:临床语音记录自动转录

Whisper-large-v3在医疗领域的应用:临床语音记录自动转录 1. 引言 每天清晨查房时,李医生都要带着录音笔记录患者的病情变化。回到办公室后,他需要花费大量时间反复听录音,手动整理成电子病历。这种场景在全国各大医院每天都在上…

作者头像 李华
网站建设 2026/4/19 7:09:46

Nunchaku-flux-1-dev赋能微信小程序:前端实现AI头像生成功能

Nunchaku-flux-1-dev赋能微信小程序:前端实现AI头像生成功能 最近在逛一些社交平台,发现很多朋友都在用AI给自己生成各种风格的头像,从动漫风到油画感,特别有意思。但通常要么得用电脑,要么得下载专门的App&#xff0…

作者头像 李华
网站建设 2026/4/19 7:04:34

弦音墨影应用场景深度解析:为何传统CV难以替代墨染影动定位能力

弦音墨影应用场景深度解析:为何传统CV难以替代墨染影动定位能力 1. 引言:当传统CV遇到水墨智能 在视频理解与视觉定位领域,传统计算机视觉技术已经发展了数十年。从早期的边缘检测、特征提取,到后来的深度学习目标检测&#xff…

作者头像 李华