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

浏览器历史堆栈管理 #56

Open
Gesangs opened this issue Nov 28, 2018 · 0 comments
Open

浏览器历史堆栈管理 #56

Gesangs opened this issue Nov 28, 2018 · 0 comments

Comments

@Gesangs
Copy link

Gesangs commented Nov 28, 2018

前言

先说背景,在商品列表中,每一个商品都有详情入口,跳转到新的页面后,列表页会被销毁。

再说这样一个场景,这个列表很长,浏览到列表中部时,进入某个商品详情页,再返回时,列表页就刷新了,列表回到了顶部。这样体验很不好...... 然后需求就很明确了,如何在从详情页回到列表页之后,回到原始浏览位置,甚至列表页保持原样。

这里参考对话框浮层的做法,用一个覆盖全屏的浮层,利用History的历史堆栈,使其拥有页面的基本功能(前进、后退)。

History API

借用栈和指针的概念介绍一下History的接口,文档中并未说明Histroy是个堆栈,这里只是借用一下

pushState

history.pushState(stateObject, title, url) 包括三个参数。

  1. stateObject用于存储该url对应的状态对象,该对象可在onpopstate事件中获取,也可通过history.state获取。

  2. title是标题,目前浏览器并未实现。

  3. url则是设定的url。一般设置为相对路径,如果设置为绝对路径时需要保证同源。若不传则默认为当前url。

history.pushState()向栈中压入一个指定url的记录,然后将指针指向这个记录,并截去这个记录之后的所有记录,使之成为栈顶(如下图);无副作用的将当前url更改为传入的url(修改hash值也不会触发hashchange事件)
image

replaceState

与pushState参数相同,含义也相同。唯一的区别在于replaceState是仅仅是将当前指针指向的记录更改为传入url。如上图

back、forward和go

这三个方法作用仅在于,移动指针并触发popstate事件,并不会改变histroy的长度(histroy.length)。

onpopstate

在不改变document的前提下,一旦当前指针改变(包括浏览器的前进后退)就会触发onpopstate事件。并在指针修改之后才触发。监听这个事件会传入一个对象,包含指针指向的记录信息。

Talk is cheap, Show me the code

请看这里👉code

详情页不仅要从某个页面的商品点击进入,更要通过url作为独立的页面展示,所以详情页有两种存在形式:

  1. 依附于某个页面,作为浮层的形式存在
  2. 作为一个独立的页面存在(当然这里页面还是SPA中的页面的意思,由router控制)

首先看这段代码
image
做了3件事:

  1. 向历史记录堆栈中压入一条记录
  2. 监听popstate事件
  3. 唤起详情页(浮层形式)

这里存在一个问题,当唤起页面之后,刷新或复制链接发送给人,该如何唤起浮层呢。前文提到pushState可无副作用的修改url,我们只需将url修改成和独立页面的详情页的url一样即可。这样刷新还是复制链接都将跳转到路由层的详情页,从而免去唤起浮层。

再看这段:
image
重点在于这个判断条件,上文提到popstate事件在指针移动之后触发,并传入一个对象,包含了指针指向的记录的信息。若在浮层页之后有其他不是我们预期的行为移动了指针,触发popstate事件,就会把浮层页关闭了。所以一定这里要确保指针移动后不是指向浮层页的记录,再关闭浮层。

以上。

参考:
History API与浏览器历史堆栈管理

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant