js点击返回跳转到指定页面实现过程


Posted in Javascript onAugust 20, 2020

这个功能之前有简单的带过,这次详细的讲解下原理和存在的问题(由于是运用html5的新API 所以有兼容问题,推荐移动端使用该方法)。

功能描述:

在浏览器中新建标签页并指定一个网址,网页加载完毕后,正常流程下是不允许点击返回的。因为当前标签页的相关历史记录是没有的,所以没有记录可以返回。

应客户要求,需要在这种情况下,给他的历史记录里添加一个链接(比如首页),这样在新打开的页面,点击返回就可以跳转到首页,让用户看到系统的各种功能,推广平台。

一、知识要点

HTML5引进了history.pushState()方法和history.replaceState()方法,它们允许你逐条地添加和修改历史记录条目。这些方法可以协同window.onpopstate事件一起工作。

案例:

假设 http://mozilla.org/foo.html 将执行如下JavaScript代码:

var stateObj = { foo: "bar" }; 
history.pushState(stateObj, "page 2", "bar.html");

这将让浏览器的地址栏显示http://mozilla.org/bar.html,但不会加载bar.html页面也不会检查bar.html是否存在。

假设现在用户导航到了http://google.com,然后点击了后退按钮,此时,地址栏将会显示http://mozilla.org/bar.html,并且页面会触发popstate事件,该事件中的状态对象(state object)包含stateObj的一个拷贝。该页面看起来像foo.html,尽管页面内容可能在popstate事件中被修改。

如果我们再次点击后退按钮,URL将变回http://mozilla.org/foo.html  文档将触发另一个popstate事件,这次的状态对象为null。回退同样不会改变文档内容。

pushState()方法
pushState()有三个参数:一个状态对象、一个标题(现在会被忽略),一个可选的URL地址。下面来单独考察这三个参数的细节:

状态对象(state object) — 一个JavaScript对象,与用pushState()方法创建的新历史记录条目关联。无论何时用户导航到新创建的状态,popstate事件都会被触发,并且事件对象的state属性都包含历史记录条目的状态对象的拷贝。

任何可序列化的对象都可以被当做状态对象。因为FireFox浏览器会把状态对象保存到用户的硬盘,这样它们就能在用户重启浏览器之后被还原,我们强行限制状态对象的大小为640k。如果你向pushState()方法传递了一个超过该限额的状态对象,该方法会抛出异常。如果你需要存储很大的数据,建议使用sessionStorage或localStorage。

标题(title) — FireFox浏览器目前会忽略该参数,虽然以后可能会用上。考虑到未来可能会对该方法进行修改,传一个空字符串会比较安全。或者,你也可以传入一个简短的标题,标明将要进入的状态。

地址(URL) — 新的历史记录条目的地址。浏览器不会在调用pushState()方法后加载该地址,但之后,可能会试图加载,例如用户重启浏览器。新的URL不一定是绝对路径;如果是相对路径,它将以当前URL为基准;传入的URL与当前URL应该是同源的,否则,pushState()会抛出异常。该参数是可选的;不指定的话则为文档当前URL。

注意: 在 Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1) 至 Gecko 5.0 (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2) 中,传入的对象使用JSON来进行序列化。从 Gecko 6.0 (Firefox 6.0 / Thunderbird 6.0 / SeaMonkey 2.3)开始,对象使用结构化拷贝算法来进行序列化。这将允许更多类型的对象能够安全传入。
某种意义上,调用pushState()有点类似于设置window.location='#foo',它们都会在当前文档内创建和激活新的历史记录条目。但pushState()有自己的优势:

1、新的URL可以是任意的同源URL,与此相反,使用window.location方法时,只有仅修改 hash 才能保证停留在相同的document中。

2、根据个人需要来决定是否修改URL。相反,设置window.location='#foo',只有在当前hash值不是foo时才创建一条新历史记录。

3、你可以在新的历史记录条目中添加抽象数据。如果使用基于hash的方法,你只能把相关数据转码成一个很短的字符串。

注意pushState()方法永远不会触发hashchange事件,即便新的地址只变更了hash。

popstate事件

每当激活的历史记录发生变化时,都会触发popstate事件。如果被激活的历史记录条目是由pushState所创建,或是被replaceState方法影响到的,popstate事件的状态属性将包含历史记录的状态对象的一个拷贝。

replaceState()方法

history.replaceState()操作类似于history.pushState(),不同之处在于replaceState()方法会修改当前历史记录条目而并非创建新的条目。

当你为了响应用户的某些操作,而要更新当前历史记录条目的状态对象或URL时,使用replaceState()方法会特别合适。

二、实现思路

1.利用popstate事件,监听点击返回事件。

2.触发事件时,判断当前页面的历史记录 是否有页面可以返回。

3.如果没有页面可以返回,则插入两条记录:

1)、指定的跳转页面。

2)、空记录。(使当前页面不发生变化)

三、实现方法

//返回之前没页面则返回首页
 function pushHistory() {
 if (history.length < 2) {
 var state = {
  title: "index",
  url: getHttpPrefix + "index.html"
 };
 window.history.pushState(state, "index", location.href);
 state = {
  title: "index",
  url: ""
 };
 window.history.pushState(state, "index", "");
 }
 //lll("history.state" + history.state)
 //console.log(history.state) 
}

判断当前history中的记录个数,由于页面加载的时候,浏览器会自动push进一个记录。所以要判断长度是否小于2.

塞进的state对象是为了获取对应的url链接。

注意点:

第一个pushState我将跳转url放进state对象 方便跳转操作。第二个参数没有实际意义,因为现在的浏览器基本不适用这个参数。
第三个参数是会替换当前地址栏的链接的,但是页面不会发生跳转。(我之前犯了个错误,将第三个参数设置为首页链接,导致了地址栏更改为首页链接,以至于在当前页的链接 都以首页为基础进行跳转,导致页面的所有链接都跳转错误了。)

setTimeout(function () {
 pushHistory()
 window.addEventListener("popstate", function (e) {
 lll("popstate"+window.history.state)
 if (window.history.state != null && window.history.state.url != "") {
  location.href = window.history.state.url
 }
 });
 }, 300);

这段代码放置在页面的ready事件中执行,延迟300毫秒是为了将操作滞后,防止与系统pop事件冲突。
if语句为了判断 history是否存在state对象,因为只有满足我们要求的记录才会有我们添加的state对象 所以 根据这点可以进行页面的跳转操作。
这样就可以实现我们想要的效果。

四、写在最后

缺点:

1. 很明显,就如开头提到的。只适合支持html5的浏览器使用。

2.由于插进了两条记录 ,所以 类似于 微信这种移动端的返回,需要再点击两次返回,才能推出页面,回到微信聊天窗口,用户体验不好。

总结:

这种方法 一定还可以优化和完善,只是目前我的实力不足,还不足以完善到完美的程度。

希望看到这篇文章的朋友可以得到一些启发,或者是有更好的方法实现。

Javascript 相关文章推荐
永不消失的title提示代码
Feb 15 Javascript
Javascript &amp; DHTML 实例编程(教程)(三)初级实例篇1—上传文件控件实例
Jun 02 Javascript
基于JQuery的一个简单的鼠标跟随提示效果
Sep 23 Javascript
js中通过父级进行查找定位元素
Jun 15 Javascript
javascript日期计算实例分析
Jun 29 Javascript
基于JavaScript实现树形下拉框
Aug 10 Javascript
Javascript中apply、call、bind的巧妙使用
Aug 18 Javascript
AngularJS中$http的交互问题
Mar 29 Javascript
Angular.js中定时器循环的3种方法总结
Apr 27 Javascript
js循环map 获取所有的key和value的实现代码(json)
May 09 Javascript
详解JavaScript对数组操作(添加/删除/截取/排序/倒序)
Apr 28 Javascript
解决vue单页面 回退页面 keeplive 缓存问题
Jul 22 Javascript
javascript html5摇一摇功能的实现
Apr 19 #Javascript
一些实用性较高的js方法
Apr 19 #Javascript
jQuery移动端日期(datedropper)和时间(timedropper)选择器附源码下载
Apr 19 #Javascript
JavaScript中创建对象的模式汇总
Apr 19 #Javascript
使用PHP+JavaScript将HTML页面转换为图片的实例分享
Apr 18 #Javascript
简单讲解jQuery中的子元素过滤选择器
Apr 18 #Javascript
举例讲解jQuery中可见性过滤选择器的使用
Apr 18 #Javascript
You might like
PHP常用开发函数解析之数组篇[未完结]
2012/07/30 PHP
php实现aes加密类分享
2014/02/16 PHP
Zend Framework实现自定义过滤器的方法
2016/12/09 PHP
js 数组实现一个类似ruby的迭代器
2009/10/27 Javascript
扩展easyui.datagrid,添加数据loading遮罩效果代码
2010/11/02 Javascript
Extjs4 类的定义和扩展实例
2013/06/28 Javascript
jQuery插件Tooltipster实现漂亮的工具提示
2015/04/12 Javascript
JQuery插入DOM节点的方法
2015/06/11 Javascript
JS实现队列与堆栈的方法
2016/04/21 Javascript
原生js实现放大镜特效
2017/03/08 Javascript
JavaScript编写一个贪吃蛇游戏
2017/03/09 Javascript
分享一个精简的vue.js 图片lazyload插件实例
2017/03/13 Javascript
CodeMirror js代码加亮使用总结
2017/03/25 Javascript
nodejs项目windows下开机自启动的方法
2017/11/22 NodeJs
微信小程序仿RadioGroup改变样式的处理方案
2018/07/13 Javascript
vue实现pdf导出解决生成canvas模糊等问题(推荐)
2018/10/18 Javascript
vue实现类似淘宝商品评价页面星级评价及上传多张图片功能
2018/10/29 Javascript
微信小程序中使用Async-await方法异步请求变为同步请求方法
2019/03/28 Javascript
通过图带你深入了解vue的响应式原理
2019/06/21 Javascript
python使用ctypes模块调用windowsapi获取系统版本示例
2014/04/17 Python
Python语言描述KNN算法与Kd树
2017/12/13 Python
Python3中在Anaconda环境下安装basemap包
2018/10/21 Python
python 中Arduino串口传输数据到电脑并保存至excel表格
2019/10/14 Python
Python实现队列的方法示例小结【数组,链表】
2020/02/22 Python
浅析matlab中imadjust函数
2020/02/27 Python
台湾菁英交友:结识黄金单身的台湾人
2018/01/22 全球购物
康帕斯酒店预订:Compass Hospitality(支持中文)
2018/08/23 全球购物
WatchShop法国:英国排名第一的独立手表零售商
2020/02/17 全球购物
巴西最大的玩具连锁店:Ri Happy
2020/06/17 全球购物
部队2014年终工作总结
2014/11/27 职场文书
初中差生评语
2014/12/29 职场文书
云台山导游词
2015/02/03 职场文书
2016年青少年禁毒宣传教育活动总结(学校)
2016/04/05 职场文书
基于JavaScript实现省市联动效果
2021/06/22 Javascript
MySQL图形化管理工具Navicat安装步骤
2021/12/04 MySQL
动画「进击的巨人」第86话播出感谢绘公开
2022/03/21 日漫