history相关
这里介绍的两个 API 其实挺关键的,因为现在的前端路由的话其实基本都是 pushState 和 replaceState 控制的。
HTML5 history 为 window 添加了pushState,replaceState这两个方法,还提供了一个事件popstate。具体的方法就不讲解了,直接去官网查看吧。Mozilla
于是我们可以在页面上ajax获得数据,重绘页面,然后用户在点击倒退键时,还在这个页面上。因为我们在重绘页面的时候,调用一下pushSate为history增加了一条记录。
自己遵循 commonjs 写了一个小模块,提供了检验和调用的实现,以下是代码的讲解以及提高的思路。
检验的接口:
这个 H5 的 API 支持情况很好,但是坑还是很多的。从caniuse上来看,支持程度很好,但是 android 的几个版本不支持有些尴尬。不过那几个版本非常小众。这里最终的解决是去Modernizr找的检测方法的代码,因为直接属性检测问题比较大,例如 android2.3 浏览器支持这个 pushState 的方法,但是并不支持这个方法的行为…这里还用到了 zepto
var $ = require("zepto");
var historyState = {};
historyState.ifSupport = function() {
var ua = navigator.userAgent;
if (
(ua.indexOf("Android 2.") !== -1 || ua.indexOf("Android 4.0") !== -1) &&
ua.indexOf("Mobile Safari") !== -1 &&
ua.indexOf("Chrome") === -1 &&
ua.indexOf("Windows Phone") === -1
) {
return false;
}
return window.history && "pushState" in window.history;
};
新生成页面调用的接口:
实现思路就是将原来的层隐藏,加入一个新层覆盖上去,然后调用 window.history.pushState 加一条记录,返回的时候将原来的层清理,并将最开始的层显示出来,顺便清理了这个绑定。
/**
* @param options {required} 参数对象
{
hideDiv {required} 需要隐藏的部分
addDiv {required} 新增的部分
wrapDiv {optional} 包裹的元素,若没有,默认为body
bindFunc {optional} 对页面新添加的东西绑定类似点击的事件
state {optional} 传入的数据
title {optional} 目前被忽略
url {optional} url,需求是不变
}
*/
historyState.newPage = function(options) {
var hideDiv = options.hideDiv;
var addDiv = options.addDiv;
var wrapDiv = options.wrapDiv || $("body");
var bindFunc = options.bindFunc || function() {};
var state = options.state || {};
var title = options.title || "";
var url = options.url || "";
//隐藏当前页面,并添加进新页面
hideDiv.hide();
wrapDiv.append(addDiv);
//执行一下可能存在的绑定
bindFunc();
//如果支持的话就使用新特性,不支持的话,就不处理了
if (this.ifSupport()) {
var popFunc = function(event) {
addDiv.remove();
hideDiv.show();
//手动清掉了这个方法
window.removeEventListener("popstate", popFunc);
};
window.addEventListener("popstate", popFunc);
window.history.pushState(state, title, url);
}
};
module.exports = historyState;
简单的切换调用的借口
/**
* @param options {required} 参数对象
{
hideDiv {required} 需要隐藏的部分
showDiv {required} 显示的部分
}
*/
historyState.switchPage = function(options) {
var hideDiv = options.hideDiv;
var showDiv = options.showDiv;
var state = options.state || {};
var title = options.title || "";
var url = options.url || "";
//隐藏当前页面,并添加进新页面
hideDiv.hide();
showDiv.show();
//如果支持的话就使用新特性,不支持的话,就不处理了
if (this.ifSupport()) {
var popFunc = function(event) {
hideDiv.show();
showDiv.hide();
//手动清掉了这个方法
window.removeEventListener("popstate", popFunc);
};
window.addEventListener("popstate", popFunc);
window.history.pushState(state, title, url);
}
};
不足
模块设计有些问题,导致不能嵌套,而且不能点击前进键。
因为点击即调用了 popstate 的绑定,如果想支持嵌套的话,得将 popstate 的绑定放到一个 init 的函数,这个初始化函数只调用一次就好。
然后再通过改变 url 的参数来确定到了那个页面就可以支持前进了。
这里给出思路,就不手动实现了。
后言
这个模块毕竟有兼容性问题,最后使用了 hashchange 来实现了,参见hashchange 事件。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 981909093@qq.com
文章标题:history相关
文章字数:947
本文作者:泽鹿
发布时间:2019-08-28, 16:45:23
最后更新:2019-08-28, 20:06:31
原始链接:http://panyifei.github.io/2019/08/28/前端技术/js/框架以及规范/HTML5/history相关/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。