• 使用location.hash保存页面状态


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

    语法

    location.hash

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

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

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

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

    先看看我们的需求

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

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

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

    解决思路

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

    思路如下:

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

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

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

    最终解决方案

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    (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类

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    (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()方法即可。下面的代码是我们完整的查询页面:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    (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保存页面状态的技巧,希望对大家有所帮助!

  • 相关阅读:
    (一)MySQL中的常见查询
    PCI设备内存操作函数总结 分类: 浅谈PCI 2014-05-26 17:48 580人阅读 评论(0) 收藏
    HI3531由DMA 发起PCIe 事务 分类: HI3531 浅谈PCI-E windows驱动程序WDM 2014-05-23 11:48 930人阅读 评论(0) 收藏
    hi3531的pcie atu资源重映射 分类: HI3531 浅谈PCI-E 2014-05-21 09:17 695人阅读 评论(0) 收藏
    如何访问pcie整个4k的配置空间 分类: 浅谈PCI-E 2014-05-17 15:13 858人阅读 评论(0) 收藏
    hi3531的pcie控制器使能 分类: HI3531 2014-05-15 18:01 698人阅读 评论(0) 收藏
    hi3531 SDK 编译 kernel, 修改 参数 分类: arm-linux-Ubuntu HI3531 2014-05-07 11:23 1120人阅读 评论(0) 收藏
    如何实现Linux下的U盘(USB Mass Storage)驱动 分类: arm-linux-Ubuntu 2014-05-04 18:03 565人阅读 评论(0) 收藏
    从VGA到GPU!细数二十年显卡发展历程 分类: 生活百科 2014-04-29 17:29 448人阅读 评论(0) 收藏
    VxWorks中的中断应用设计要点 分类: vxWorks 2014-04-29 17:25 494人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/aburron/p/hash.html
Copyright © 2020-2023  润新知