Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

回顾 W3C 浏览器会话历史部分 —— W3C 'session history' Part Review #9

Open
CuriosityLxn opened this issue Apr 9, 2020 · 0 comments
Labels
Web Recommendation Standard && normalization && Recommendation

Comments

@CuriosityLxn
Copy link
Owner

前提

基本上所有的现代浏览器都已实现了标签页会话。
一个标签页就承载着一个标签页会话。
标签页会话基本上就是浏览器会话。

浏览器会话

这里的会话(session)区别于客户端与服务端之间的会话:

  • 客户端与服务端之间的会话:客户端与服务端进行的一系列通讯(请求/响应对)。在这种会话中,服务端需要通过某种机制(比如 cookie)来识别出当前的请求属于哪一个会话。
  • 浏览器会话是指:在一个浏览器窗口(标签页)的生命周期中,经历的一系列文档替换(卸载旧的文档,并加载新的文档)。

会话中的文档替换

  1. 打开一个新的标签页,就开始了一个新的会话。(如果有多个标签页同时打开,说明用户同时处于多个会话当中)。
  2. 修改标签页的 URL,或点击当前页面上的超链接(且的target attribute为默认值_self),或提交表单时,就会发生一次文档替换(新的 Document 会将当前 Document 替换掉)。
    此时该标签页的会话历史(session history)中会增加一个会话历史条目(session history entry)。

修改 URL 不发生文档替换的情况:

  • 触发 window.hashchange 事件。
  • 使用 history.pushState() | history.replaceState() 方法修改会话历史。
    这两种情况会更改 URL,会改变一个会话历史条目。不会替换文档,也就不会刷新页面。
  1. history.back()history.forward()history.go() 事件和浏览器前进后退按钮,会触发 history.popState() 事件,会刷新页面。
  2. history.pushState() | history.replaceState()只会更新或添加会话历史记录,不会刷新或改变页面渲染。不会触发 popstate 事件,可在 popstate 事件回调中处理是否加载页面。可用 window.onpopstate 监听它们。pushState()方法不会触发hashchange事件,即使URL的hash片段值改变。
  3. FirefoxSafari 实现了 Back-Forward Cache,可以快速载入旧的会话历史条目。Chrome 未实现 Back-Forward Cache。
  4. PC 上通过 ctrl+shift+t,可以恢复上一次关闭的标签页及其会话历史。
    被恢复的历史条目的文档需要重新加载,Back-Forward Cache 不会随着它的历史条目一起恢复。

Back-Forward Cache

  • 在每个独立的浏览器会话中的所有页面及页面的 JS 文件状态放在内存中缓存起来。
  • 在已访问过的页面之间来回切换时,浏览器不需要重新从服务器获取代码,也不需要重新加载页面,从而提高了页面访问速度。
  • Firefox 和 Safari 默认使用这种机制缓存页面,可通过一些参数配置使页面不被缓存,具体参数参见 MDN

流程

发生:当标签页即将从一个会话历史条目 A 迁移到 B && B 的文档会替换掉 A 的文档时。

缓存:旧的文档不会被方法,而是保留在内存中并暂停其活动。这个缓存会被保存到用户关闭浏览器。

激活:通过浏览器前进/后退按钮载入旧的会话历史条目时,如果这个条目对应的文档有被缓存,那么直接从缓存中恢复这个文档并恢复其活动。

History

Travel through and manipulate the browser history
操作浏览器历史记录,一般用来在会话历史里来回导航。

pushState() 方法

三个参数:state object | title | URL(非必需,若有需同源)

history.pushState()window.location = "#foo" 基本等效,都会新建一条新的会话历史条目。

pushState() 和 window.location 在设置 URL 时的区别
  1. pushState() 设置的 URL 不可跨域。window.location 可跨域。
  2. pushState() 不会打开新文档。window.location 只在更改 hash(触发 hashchange)时,才不会打开新的文档。
  3. pushState() 不会更改 URL。当前 URL 的 hash 值不为 #foo 时,window.location 才会创建一条新的历史条目。
  4. pushState() 创造的历史条目中,可以直接添加搜索参数数据。window.location 需要将所有搜索参数编码成字符串。

注意:

history.pushState() 永远不会触发 hashchange 事件,哪怕新旧 URL 只有 hash 不同。

replaceState() 方法

修改当前会话历史条目。可用来拦截用户返回页面。

pushState()replaceState() 不会立马导航至新的 URL,只会使 URL 栏中的地址发生改变,且不会使浏览器检查到新条目的存在。需触发过 popstate() 方法后才会导航至新 URL。

popstate 事件

  • 每次会话记录变换激活都会在 window 上触发 popstate() 事件。
  • 当前页面 DOM 加载完成后才会触发 popstate() 事件。
  • 如果激活的会话记录是使用 pushState() 方法创建的或通过 replaceState() 更新的,popstate() 事件的 state 就会包括该条目 state 对象的一个副本。

读取当前 state 对象

  • 一般情况下,state 对象为 null。比如页面加载时。
  • 拿到 state 的值,需要满足:
    1. 给页面设置了 state 对象(使用 pushState()| replaceState())。
    2. 该页面触发 popstate()(浏览器的前进后退按钮 | 重启浏览器等)。
  • 页面刷新不会触发 popstate(),但页面会接收到 onload

Location

The Window.location read-only property returns a Location object with information about the current location of the document.

用来查看或改变当前 Window 对象 或 Document 对象的位置(URL,资源地址)。

Though Window.location is a read-only Location object, you can also assign a DOMString to it.

MDN 有言,Window.location 是一个只读Location 对象。
此处的“只读”指的是,Window.location 始终返回的是一个 Location 对象,不会因为给它赋值了一个字符串而变成一个字符串。

var obj = {}; // 此时 obj 是一个空对象
obj = '123'; // 赋值后 obj 变成了字符串“123”

window.location; // 此时 window.location 是一个 Location 对象
/* Output:
Location {
    hash: ""
    host: "developer.mozilla.org"
    hostname: "developer.mozilla.org"
    href: "https://developer.mozilla.org/en-US/docs/Web/API/Window/location"
    origin: "https://developer.mozilla.org"
    pathname: "/en-US/docs/Web/API/Window/location"
    ...
}
*/
window.location = 'https://m.helijia.com/#/?_k=e0g33h'; // 赋值后 window.location 还是 Location 对象,只是 Location 对象的属性值发生了变化。
/* Output:
Location {
    hash: "#/?_k=e0g33h"
    host: "m.helijia.com"
    hostname: "m.helijia.com"
    href: "https://m.helijia.com/#/?_k=e0g33h"
    origin: "https://m.helijia.com"
    pathname: "/"
    ...
}
*/

assign(url) 方法

location.assign(url)等效于 location.href = url

reload(true/false) 方法

true:从服务器重新加载资源。
false:从浏览器缓存中重新加载。

replace(url) 方法

用 url 指向的资源替换当前资源,并替换当前会话历史条目,被替换掉的会话历史将再也无法被访问到。
不同于 reload(), replace(url) 总是从服务器重新加载其 url 指向的页面。

toString() 方法

返回当前 URL,结果与 location.href 相同,但不可写。

Location && History 方法对应

  • location.href = url 等效于使用 history.pushState() 修改URL,会创建一条新会话记录。
  • location.replace(url) 等效于使用 history.replaceState() 修改URL,替换当前会话记录。不同于 location.reload() 方法从客户端重新加载页面,location.replace(url)总是重新加载其 url 指向的页面。
  • location (通过打开新文档的方式进行文档替换),当前会话历史条目的资源替换刷新页面。
  • history 和浏览器前进后退按钮通过选择激活不同历史条目的方式刷新页面。
@CuriosityLxn CuriosityLxn changed the title 回顾 W3C 浏览器会话历史部分 —— W3C session history review 回顾 W3C 浏览器会话历史部分 —— W3C 'session history' Part Review Apr 9, 2020
@CuriosityLxn CuriosityLxn added the Web Recommendation Standard && normalization && Recommendation label Apr 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Web Recommendation Standard && normalization && Recommendation
Projects
None yet
Development

No branches or pull requests

1 participant