
需求应该都很清晰,就是点击查询表单,用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。(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反序列化objectupdateFormByHashQuery();$("#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);};})(); 总结