移动端页面栈 · 整页独立 demo
这是移动端页面栈 / 模态栈那台引擎的整页独立版:同一套声明式 reconcile——URL → 这一刻该挂哪几层,与实际挂载做
diff,公共前缀保活、多出来的销毁、缺的补上——只是这里把它放进一台占满舞台的手机里,让你直接开着玩,而不是隔着讲解页看缩略演示。引擎的完整拆解(stackFromPath 怎样把路径累积成链、reconcile 怎样按公共前缀做
diff、直达时背景怎样被合成)都在讲解版里,本页只留下可上手的成品。
本页是一个受控模拟:它不改动浏览器真实的 history 与 location,导航、返回、侧滑全部走组件内部维护的一份栈状态。原始的整页版占满整个视口、吃进刘海与底部安全区、直接由真实 history (hash)
驱动,因此手机系统返回手势能直接弹栈;搬进讲解文档后,那种「占满视口」的沉浸感换成了这台手机框,手感与逻辑保持一致。
1 · 三种导航,一台引擎
手机里能触发的动作分三类,底层都收敛到同一个 reconcile:
| 动作 | 触发方式 | 栈的变化 |
|---|---|---|
| push | 点绿色 / 紫色的可跳转行 | 顶层水平滑入,下层左移压暗、保活不卸载 |
| pop | 点顶栏 ‹,或从左缘向右侧滑 |
顶层离场动画结束后销毁,下层归位复原 |
| 模态 | 点「设置」进入 | 模态栈从底部滑入,盖住背景页(背景仍保活),顶栏 ✕ 一次弹掉整层 |
返回时上一页原封不动,唯一的原因是它从没被销毁过。 push 只是在栈上叠一层、把下层盖住,下层的 DOM、滚动位置、展开态都留在原地;pop 才销毁顶层。在首页往下滚一段,进详情或开设置转一圈再返回,首页的滚动位置分毫不差——这正是原生 UINavigationController / Android back stack 的语义。
2 · 直达深层地址:背景是被合成出来的
控制区那排 ❄️ 按钮模拟冷启动:清空已挂载的层,直接从某个深层地址重建。直达 #/settings/account/security 时,它底下本没有任何背景页——引擎按
stackFromPath 的规则,先铺一段背景链(默认首页,或从记下的来源页取回),再接上设置自己的链,于是返回时有处可去。冷启动到不同深度,看这一层背景如何被凭空补齐。
侧滑返回只对水平 push 的栈顶生效:必须从左缘起手、横向位移超过阈值才提交弹栈,否则回弹复位;纵向滑动会被判定为正文滚动而放弃。模态栈的栈底(设置那一层)是垂直滑入的,只能用顶栏 ✕ 关闭,不吃侧滑。
3 · 相关页
- 移动端页面栈 / 模态栈——本页的讲解版:左手机 + 右侧「当前挂载的 DOM 栈」面板,把
stackFromPath、reconcile diff、直达合成背景三块内核逐段拆开。 - 页面栈的 vue-router 实现——同一套「基础层级 + 设置模态栈 + 直达合成背景」,换成 vue-router 的
keep-alive/<transition>/meta/ 守卫拼出来。 - 客户端路由 · push / replace 与 history 栈——这台引擎建立在 push / pop 与 history「条目 + 指针」模型之上,那页把这套栈本身讲透。