网页导航接口规范 0.1.0
本包让浏览器里的豫言应用改变当前页面的地址与历史记录:离开当前页去别处、替换当前地址、重载,以及在不离开本页的前提下压入或替换历史记录(用地址栏的查询参数记录“打开了哪个项目、哪个版本”这类状态)。回退与前进产生的 popstate、hashchange 事件不在本包,用[网页事件接口](../网页事件/规范.汉语.md)订阅“窗口”取得(类型 历史)。读取当前完整网址用网页文树包的 读取页面网址,解析与改写网址用网址定位(解析绝对网址部件、根据根址解析网址部件)与网址查询两个包。应用依赖本包后,全部函数都必须实现。
地址规则
所有函数的“地址”参数都按当前页面网址解析(可以是绝对网址,也可以是 /路径、?查询、#锚 等相对引用),并满足:
- 长度至多 8192 个 UTF-16 码元,不得为空,不得含 ASCII 控制字符(0 至 31、127)和反斜杠;
- 解析后的协议只能是
http:或https:(javascript:、data:、blob:、file:等一律拒绝)。
违规抛豫言事故(中文消息,可捕获)。
函数
前往网址 : 字符串 → 有
等价于 location.assign(地址):在历史里留下一条并前往新地址(可以是另一个来源)。页面随即卸载,本次调用之后的应用代码不保证执行;需要在离开前做的事(保存草稿等)应在调用之前完成。
替换当前网址 : 字符串 → 有
等价于 location.replace(地址):用新地址替换当前历史记录,后退不会回到旧地址(登录跳转常用)。页面随即卸载。
重载页面 : 有 → 有
等价于 location.reload()。页面随即卸载。
压入历史 : 字符串 → 有、替换历史 : 字符串 → 有
等价于 history.pushState(null, '', 地址) 与 history.replaceState(null, '', 地址):只改地址栏与历史,不重新载入、不触发 `popstate`,状态对象恒为 null。地址解析后必须与当前页面同源,否则抛事故(浏览器本身也会拒绝)。典型用法:选中一个项目时 压入历史("/cloud/?project=…"),筛选变化时 替换历史(…)。
移动历史 : 整数 → 有
等价于 history.go(n):负数后退、正数前进;0 无效(重载用 重载页面),绝对值至多 50。移动异步完成,浏览器随后触发 popstate(同一文档内)或直接卸载页面(离开本文档时)。
与其他包的配合
- 读取当前地址:网页文树包
读取页面网址、读取页面查询参数。 - 拼装带查询的地址:网址查询包(
编码查询串、设置网址查询参数)与网址包(编码网址成分)。 - 回退与前进:网页事件包
订阅界面事件("窗口", "popstate", "{}"),事件类型历史,详情{"网址":当前地址,"状态":null}。应用收到后自行决定重新读取地址并刷新界面,或调用重载页面。
限额与失败
| 项 | 限额 |
| --- | --- |
| 地址长度 | 至多 8192 个 UTF-16 码元 |
| 移动历史 | 1 至 50 或 −50 至 −1 |
违规调用(地址不合规、非同源的压入或替换、步数越界)抛事故;浏览器因页面正在卸载或历史操作过于频繁而拒绝时同样抛事故。宿主已关闭时抛事故。
一致性样例
- 当前页
https://例.站/cloud/?service=code:压入历史("/cloud/?project=甲")后读取页面网址为https://例.站/cloud/?project=甲,popstate不触发;移动历史(-1)后回到原地址,并收到一个类型历史、名称popstate的事件。 压入历史("https://别处.站/"):抛事故(非同源)。前往网址("javascript:alert(1)")、前往网址("data:text/html,x"):抛事故。前往网址("?panel=终端")解析为当前路径加新查询后前往。替换历史("#锚")后地址带#锚,历史条数不变。
边界
本包不规定:历史状态对象(恒为 null)、window.open(新窗口与弹窗)、beforeunload 询问、Navigation API、单页路由库、下载与链接点击(用 a[href] 加界面事件)。