「Web 技巧」路由间带点贵礼物走亲戚

74 阅读2分钟

问题

Web 开发路由跳转常见的一个需求:一个路由(A)到另一个路由(B)的同时会带点参数。通常情况下我们会把参数放到 URL 的 query 里面去比如:

image.png

https://example.com:8042/over/there?name=ferret
                                    \_________/
                                         |
                                       query
# \_________/ 来源:https://github.com/Cyphrme/URLFormJS/blob/master/README.md?plain=1
                                       

query 非常好用,正常满足了需求,而利于用户分享。哪怕 query 里面的参数多点也没问题,通常情况下我们都不会超过浏览器对 URL 大小的限制。

这也就是讲路由之间串亲戚都比较抠,不会带太贵重的礼物,现在加入极端情况下,路由(A)到路由(B)携带的参数过大(比如很多很多查询条件),这就很危险,URL 过长很有可能截断。

现在我们让用户保存分享的便利情况下如何实现这个需求呢?

fragment

答案就是使用 URL 的 fragment,即 hash 路由传参而不使用 query 传参。

https://example.com:8042/over/there?name=ferret#balabalabalab
                                                \___________/
                                                     |
                                                  fragment

浏览器路由 fragment 的好处在于:

  1. 保留了分享功能,带有 Fragment 的链接,其他人可以访问同样的页面。
  2. 节省了 HTTP 资源,因为 Fragment 的内容不会被发送到服务器。
  3. 存储无限制: Fragment 路由还可以用来管理应用程序的状态。因为不发送给服务端,浏览器不会限制 Fragment 的长度,一个大小毫无限制的存储器诞生了。

实现

JSON 肯定不能直接显示在 URL 中,所以使用最常用的百分比编码进行编码解码,下面代码的 compress 主要压缩空格和缩进去。

编码:

const stateString = JSON.stringify(appState, null, null); // appState is a json object
const encoded = encodeURIComponent(stateString); // Push that `encoded` string to the url 

解码

const decoded = decodeURIComponent(encoded); // same encoded as above, but read from url
const newState = JSON.parse(decoded); // Now load your application with the newState

Fragment 应用

Fragment 应用

knotend 是一个用来画流程图的工具,但是它的数据并没有存储在后端,而是选择了存储在 URL 的 Fragment 中,这就牛皮了,无限无成本存储,不用请求接口用户打开超快,还可以通过 URL 分享,恢复和重做功能直接利用浏览器的前进后退就能完成。

唯一的缺点就是 URL 可能过于臃肿。

参考