按关键词阅读:
- state:用于存储该 URL 对应的状态对象 , 可以通过 history.state 获取
- title:标题 , 目前浏览器并不支持
- URL:定义新的历史 URL 记录 , 需要注意 , 新的 URL 必须与当前 URL 同源 , 不能跨域
文章插图
通过 history.pushState({ tag: "cart" }, "", "cart.html"), 将 /home.html 变成 /cart.html 时 , 只有 URL 发生了改变 ,cart.html 页面并没有加载 , 甚至浏览器都不会去检测该路径是不是存在 。 这也就是证明了 , pushState 在不刷新页面的情况下修改浏览器 URL 链接 , 单页面路由的实现也就是利用了这一个特性 。
细心地童鞋应该发现了 , 通过 pushState 设置新的 URL 的方法与通过 window.location='#cart' 设置 hash 值改变 URL 的方法有相似之处:URL 都发生了改变 , 在当前文档内都创建并激活了新的历史记录条目 , 但页面均没有重新渲染 , 浏览器没有发起请求 。 那前者的优势又是什么呢?
- 新的 URL 可以是任意同源的 URL , 而 window.location , 只能通过改变 hash 值才能保证留在当前 document 中 , 浏览器不发起请求
- 新的 URL 可以是当前 URL , 不改变 , 就可以创建一条新的历史记录项 , 而 window.location 必须设置不同的 hash 值 , 才能创建 。 假如当前URL为 /home.html#foo, 使用 window.location 设置 hash 时 , hash值必须不能是 #foo, 才能创建新的历史记录
- 可以通过 state 参数在新的历史记录项中添加任何数据 , 而通过 window.location 改变 hash 的方式 , 只能将相关的数据转成一个很短的字符串 , 以 query 的形式放到 hash 值后面
- 虽然 title 参数现在还不能被所有的浏览器支持 , 前端发展这么快 , 谁能说的准之后发生的事情呢!
文章插图
从上面的动画 , 我们就可以知道 , 通过 history.replaceState({ tag: "cart" }, "", "cart.html") 改变 URL 之前 , history 的历史记录为 /classify.html 、 /home.html, URL 改变之后 , 点击浏览器后退键 , 直接回到了 /classify.html, 跳过了 /home.html。 也就证明了 replaceState 将历史记录中的 /home.html 修改为 /cart.html, 而不是新建 /cart.html。
window.onpopstate()通过 a 标签或者 window.location 进行页面跳转时 , 都会触发 window.onload 事件 , 页面完成渲染 。 点击浏览器的后退键或前进键 , 根据浏览器的不同机制 , 也会重新加载(Chrome 浏览器) , 或保留之前的页面(Safari 浏览器) 。 而对于通过 history.pushState() 或 history.replaceState() 改变的历史记录 , 点击浏览器的后退键或前进键页面是没有反应的 , 那该如何控制页面渲染呢?为了配合 history.pushState() 或 history.replaceState() , HTML5 还新增了一个事件 , 用于监听 URL 历史记录改变:window.onpopstate() 。
官方对于 window.onpopstate() 事件的描述是这样的:
【SPA 路由三部曲之核心原理】每当处于激活状态的历史记录条目发生变化时 , popstate 事件就会在对应 window 对象上触发 。如果当前处于激活状态的历史记录条目是由 history.pushState() 方法创建,或者由 history.replaceState() 方法修改过的, 则 popstate 事件对象的 state 属性包含了这个历史记录条目的 state 对象的一个拷贝 。 调用 history.pushState() 或者 history.replaceState() 不会触发 popstate 事件 。 popstate 事件只会在浏览器某些行为下触发, 比如点击后退、前进按钮(或者在JavaScript 中调用 history.back()、history.forward()、history.go()方法) , 此外 , a 标签的锚点也会触发该事件 。
第一次读到这段话的时候似懂非懂 , 思考了很久 , 也做了很多的例子 , 发现其中的坑很多 , 这些坑主要是因为每个浏览器机制不同 。 官方文档对 window.onpopstate() 的描述很少 , 也有很多不明确的地方 , 根据自己的测试 , 来拆解一下官网描述 , 如果有不对的 , 还希望大家指出 。
1.每当处于激活状态的历史记录条目发生变化时 , popstate 事件就会在对应 window 对象上触发 。 对这句话的理解是 , 在浏览器中输入一个 URL, 使其处于激活状态 , 不管通过哪种方式 , 只要 URL 改变 , popstate 就会触发 。 但实际情况却是:只有通过 pushState 或 replaceState 改变的 URL , 在点击浏览器后退键的时候才会触发 , 如果是通过 a 标签或 window.location 实现 URL 改变(不是改变锚点)页面跳转 , 在点击浏览器回退键的时候 , 并不会触发 。 对这种情况 , 我有两个猜测:
稿源:(未知)
【傻大方】网址:http://www.shadafang.com/c/111J3025H020.html
标题:SPA 路由三部曲之核心原理( 三 )