location.hash保存页面状态的技巧


Posted in Javascript onApril 28, 2016

hash 属性是一个可读可写的字符串,该字符串是 URL 的锚部分(从 # 号开始的部分)。

语法

location.hash

在我们的项目中,有大量ajax查询表单+结果列表的页面,由于查询结果是ajax返回的,当用户点击列表的某一项进入详情页之后,再点击浏览器回退按钮返回ajax查询页面,这时大家都知道查询页面的表单和结果都回到了默认状态。

如果每次返回页面都要重新输入查询条件,或有甚者还得转到列表的第几页,那这种体验用户真的要抓狂了。

在我们的项目中,写了一个很简单的JavaScript基类来处理location.hash从而保存页面状态,今天在此就分享给大家。

(本文的内容可能对于JavaScript初学者来讲有点难度,因为涉及到JS面向对象的知识,如定义类、继承、虚方法、反射等)

先看看我们的需求

我们的项目是一个基于微信的H5任务管理系统,要完成的页面原型如下图所示:

location.hash保存页面状态的技巧

需求应该都很清晰,就是点击查询表单,用ajax返回查询结果,然后点击列表中的某一个任务进入任务详情页。由于管理员(项目经理)通常会一次处理多个任务,所以就会不断在任务详情页跟查询列表页切换,这时如果按返回键不能保存查询页面状态的话,那每次返回查询页面都要重新输入查询条件,这样的体验肯定是不能忍受的。

所以,我们需要想办法将页面状态保存下来,以便用户按回退键的时候,查询条件和结果都还在。

解决思路

保存页面状态的思路有很多啦,但是我们觉得用location.hash应该是最好的方法。

思路如下:

1.用户输入查询条件并点击确定后,我们将查询条件序列化成一个字符串,并通过“#”将查询条件加到url后面得到一个新的url,然后调用location.replace(新的url)修改浏览器地址栏中的地址。

2.当用户按回退键回退到查询页面时,也可以说是页面加载时,将location.hash反序列化成查询条件,然后将查询条件更新到查询表单并执行查询即可。

思路很简单,关键的地方就是location.replace方法,这个方法不仅仅是修改浏览器中地址栏的url,更重要的是会在window.history中替换当前页面的记录。如果不用location.replace方法,那么每次回退都会回退到上一个查询条件。当然,这样的需求可能对某些项目还有用。

最终解决方案

如果本文只是分享上面的解决思路,那价值就不大了。本文的价值应该是我们写的那个虽然简单但是却很强大的JavaScript类。

如果你看明白了上面的解决思路,那就看看这个简单的JavaScript类吧:

(function() {
if (window.HashQuery) {
return;
}
window.HashQuery = function() {
};
HashQuery.prototype = {
parseFromLocation: function() {
if (location.hash === '' || location.hash.length === ) {
return;
}
var properties = location.hash.substr().split('|');
var index = ;
for (var p in this) {
if (!this.hasOwnProperty(p) || typeof this[p] != 'string') {
continue;
}
if (index < properties.length) {
this[p] = properties[index];
if (this[p] === '-') {
this[p] = '';
}
}
index++;
}
},
updateLocation: function() {
var properties = [];
for (var p in this) {
if (!this.hasOwnProperty(p) || typeof this[p] != 'string') {
continue;
}
var value = this[p];
properties.push(value === '' ? '-' : value);
}
var url = location.origin + location.pathname + location.search + "#" + properties.join('|');
location.replace(url);
}
};
})();

这个类只有2个方法,HashQuery.parseFromLocation() 方法从location.hash反序列化为HashQuery子类的实例,HashQuery.updateLocation() 方法将当前HashQuery子类的实例序列化并更新到window.location。

可以看到HashQuery这个类没有任何属性,那是因为我们只定义了一个基类,类的属性都在子类中进行定义。这也是符合实际的,因为查询条件都只有在具体的页面才知道有哪些属性。

另外,请注意这里的序列化和反序列化。这里的序列化仅仅是利用JavaScript反射机制将实例的所有字符串属性(按顺序)的值用“|”分隔;而序列化则是将字符串用“|”分隔后,再利用反射更新到实例的属性(按顺序)。

如何使用HashQuery类

使用的时候就非常简单了。

第一步,定义一个子类,将需要用到的查询条件都加到字符串属性当中,如我们的代码:

(function() {
window.TaskSearchHashQuery = function () {
HashQuery.constructor.call(this);
this.iterationId = '';
this.assignedUserId = '';
this.status = '';
this.keyword = '';
};
TaskSearchHashQuery.constructor = TaskSearchHashQuery;
TaskSearchHashQuery.prototype = new HashQuery();
})();

第二步,在查询页面调用HashQuery.parseFromLocation() 和 HashQuery.updateLocation()方法即可。下面的代码是我们完整的查询页面:

(function() {
var urls = {
list: "/app/task/list"
};
var hashQuery = null;
var pager = null;
$(document).ready(function () {
hashQuery = new TaskSearchHashQuery();
hashQuery.parseFromLocation();//在这里调用的哦,从location反序列化object
updateFormByHashQuery();
$("#btnSearch").click(function() {
updateHashQueryByForm();
hashQuery.updateLocation();//在这里调用的哦,将查询条件序列化之后更新到location.hash
$("#lblCount").html("加载中...");
pager.reload();
page.hideSearch();
});
pager = new ListPager("#listTasks", urls.list);
pager.getPostData = function(index) {
return "pageIndex=" + index + "&pageSize=" + "&projectId=" + page.projectId
+ "&iterationId=" + hashQuery.iterationId
+ "&assignedUserId=" + hashQuery.assignedUserId
+ "&status=" + hashQuery.status
+ "&keyword=" + hashQuery.keyword;
};
pager.onLoaded = function() {
$("#lblCount").html("共 " + $("#hfPagerTotalCount").val() + " 个任务");
$("#hfPagerTotalCount").remove();
};
pager.init();
});
function updateHashQueryByForm() {
hashQuery.iterationId = $("#ddlIterations").val();
hashQuery.assignedUserId = $("#ddlUsers").val();
hashQuery.status = $("#ddlStatuses").val();
hashQuery.keyword = $("#txtKeyword").val();
};
function updateFormByHashQuery() {
$("#ddlIterations").val(hashQuery.iterationId);
$("#ddlUsers").val(hashQuery.assignedUserId);
$("#ddlStatuses").val(hashQuery.status);
$("#txtKeyword").val(hashQuery.keyword);
};
})();

总结

这就是我们项目中使用location.hash来保存页面状态的全部知识了。不知道大家的WEB项目中是如何处理这样的需求的呢?

以上内容是小编给大家介绍的location.hash保存页面状态的技巧,希望对大家有所帮助!

Javascript 相关文章推荐
浅析js中取绝对值的2种方法
Jul 09 Javascript
推荐 21 款优秀的高性能 Node.js 开发框架
Aug 18 Javascript
使用script的src实现跨域和类似ajax效果
Nov 10 Javascript
jQuery插件expander实现图片翻转特效
May 21 Javascript
JS获取随机数和时间转换的简单实例
Jul 10 Javascript
JS实现太极旋转思路分析
Dec 09 Javascript
jquery获取链接地址和跳转详解(推荐)
Aug 15 jQuery
JavaScript实现带有子菜单和控件的slider轮播图效果
Nov 01 Javascript
vue使用axios实现文件上传进度的实时更新详解
Dec 20 Javascript
浅谈JavaScript 代码整洁之道
Oct 23 Javascript
Vue组件间的通信pubsub-js实现步骤解析
Mar 11 Javascript
vue实现倒计时功能
Mar 24 Vue.js
字符串反转_JavaScript
Apr 28 #Javascript
使用 stylelint检查CSS_StyleLint
Apr 28 #Javascript
基于BootStarp的Dailog
Apr 28 #Javascript
浅析jquery与checkbox的checked属性的问题
Apr 27 #Javascript
JavaScript 消息框效果【实现代码】
Apr 27 #Javascript
浅析jQuery事件之on()方法绑定多个选择器,多个事件
Apr 27 #Javascript
js实现人民币大写金额形式转换
Apr 27 #Javascript
You might like
php面向对象编程self和static的区别
2016/05/08 PHP
微信公众号开发之获取位置信息php代码
2018/06/13 PHP
Thinkphp5框架使用validate实现验证功能的方法
2019/08/27 PHP
浅谈Javascript事件处理程序的几种方式
2012/06/27 Javascript
jQuery在html有效在jsp无效的原因及解决方法
2013/08/02 Javascript
JS生成随机字符串的多种方法
2014/06/10 Javascript
Javascript 多物体运动的实现
2014/12/24 Javascript
用JavaScript获取页面文档内容的实现代码
2016/06/10 Javascript
Vue.js中 v-model 指令的修饰符详解
2018/12/03 Javascript
JavaScript学习笔记之图片库案例分析
2019/01/08 Javascript
js实现html滑动图片拼图验证
2020/06/24 Javascript
vue自定义组件(通过Vue.use()来使用)即install的用法说明
2020/08/11 Javascript
[40:50]2014 DOTA2国际邀请赛中国区预选赛 5 23 CIS VS LGD第四场
2014/05/24 DOTA
[03:14]2014DOTA2西雅图国际邀请赛 EG战队巡礼
2014/07/07 DOTA
[01:51]2014DOTA2西雅图邀请赛 MVP 外卡赛black场间采访
2014/07/09 DOTA
python装饰器使用方法实例
2013/11/21 Python
不可错过的十本Python好书
2017/07/06 Python
python多进程使用及线程池的使用方法代码详解
2018/10/24 Python
python 多进程共享全局变量之Manager()详解
2019/08/15 Python
python numpy 常用随机数的产生方法的实现
2019/08/21 Python
使用Python制作一个打字训练小工具
2019/10/01 Python
TensorFlow的环境配置与安装方法
2021/02/20 Python
基于HTML5 audio元素播放声音jQuery小插件
2011/05/11 HTML / CSS
基于Modernizr 让网站进行优雅降级的分析
2013/04/21 HTML / CSS
乐高西班牙官方商店:LEGO Shop ES
2019/12/01 全球购物
屈臣氏泰国官网:Watsons TH
2021/02/23 全球购物
实习单位鉴定评语
2014/04/26 职场文书
主题团日活动总结
2014/06/25 职场文书
车贷收入证明范本
2014/09/14 职场文书
检查机关党的群众路线个人整改措施
2014/10/04 职场文书
个性发展自我评价2015
2015/03/09 职场文书
施工员岗位职责范本
2015/04/11 职场文书
导游词之海南-南湾猴岛
2019/10/12 职场文书
CocosCreator ScrollView优化系列之分帧加载
2021/04/14 Python
python中pymysql包操作数据库方法
2022/04/19 Python
Linux中各个目录的作用与内容
2022/06/28 Servers