zoukankan      html  css  js  c++  java
  • window.location.hash属性介绍

    window.location.hash属性介绍

    location是javascript里边管理地址栏的内置对象,比如location.href就管理页面的url,用location.href=url就可以直接将页面重定向url。而location.hash则可以用来获取或设置页面的标签值。比如http://domain/#admin的location.hash="#admin"。利用这个属性值可以做一个非常有意义的事情。

    很多人都喜欢收藏网页,以便于以后的浏览。不过对于Ajax页面来说的话,一般用一个页面来处理所有的事务,也就是说,如果你浏览到一个Ajax页面里边有意思的内容,想将它收藏起来,可是地址只有一个呀,下次你打开这个地址,还是得像以往一样不断地去点击网页,找到你钟情的那个页面。另外的话,浏览器上的“前进”“后退”按钮也会失效,这于很多习惯了传统页面的用户来说,是一个很大的使用障碍。

    那么,怎么用location.hash来解决这两个问题呢?其实一点也不神秘。

    比如,我的作者管理系统,主要功能有三个:普通搜索、高级搜索、后台管理,我分别给它们分配一个hash值:#search、#advsearch、#admin,在页面初始化的时候,通过window.location.hash来判断用户需要访问的页面,然后通过javascript来调整显示页面。比如:

    var hash; 

    hash=(!window.location.hash)?"#search":window.location.hash; 

    window.location.hash=hash; 

      //调整地址栏地址,使前进、后退按钮能使用 

    switch(hash){   

    case "#search":  

        selectPanel("pnlSearch");   //显示普通搜索面板  

        break;    

    case "#advsearch":    

          

    case "#admin":  

         

    }

    通过window.location.hash=hash这个语句来调整地址栏的地址,使得浏览器里边的“前进”、“后退”按钮能正常使用(实质上欺骗了浏览器)。然后再根据hash值的不同来显示不同的面板(用户可以收藏对应的面板了),这就使得Ajax页面的浏览趋于传统化了。

     

     

    用HTML5来控制浏览器地址栏,并支持前进和后退

     

    现在单页无刷新应用里,即用Ajax获取数据,通过前端JS渲染页面,用户在一个页面里完成几乎所有的事情。为了让浏览器记住并标示出当前所处的页面,需要用锚点,即location.hash来记录参数。因为直接修改location.href的话会造成页面跳转。下面介绍的方法是HTML5新增加的方法,可以自由的控制浏览器历史记录,使得地址栏真正改变而不是各种#。

     

     

    以下为转载:

    原文地址:

    {

    '第一段': 'http://note.sdo.com/u/1185659399/n/6GXE7~jE5sx0LX0xI000pW',

    '第二段': 'http://hi.baidu.com/kooboy/blog/item/6f2c31adadedc2134b36d691.html',

    '文档': 'https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history'

    }

     

    第一段

    1. 问题是什么?

     

    可能未写过 Ajax 应用的人会好奇,改变 URL 并且支持后退是这么难的事么?这在现阶段确实是个难题。产生问题的地方主要有两点。

    1.1 改变当前 URL 会让浏览器载入页面

     

    Javascript 有一个函数可以改变当前 URL 路径。

    window.location = '/' 

    如果在浏览器的网页调试程序(firebug 或 chrome 原生调试工具)的控制台输入这行代码,页面会马上跳转到当前网站的根目录。这跟用户点击了一个超链接的效果一样。

    而如果只改变 URL 的 # 号后面部分,不会导致浏览器重新载入网页。因为浏览器认为 # 号是当前页面的一个锚点,也就不需要刷新了。

    window.location = '#here' // 不会导致页面刷新 

    稍后还会利用到这个特性。

    1.2 浏览器不懂得记录 Ajax 调用的状态

     

    因为 Ajax 调用是多种多样的,统计代码会引发 Ajax,广告会引发 Ajax,页面定时刷新会引发 Ajax,所以浏览器并不知道如何记录 Ajax 的状态。

    如果用户点击一个链接通过 Ajax 刷新了页面,然后进入其他页面,再然后点了返回按钮,会产生什么状况呢?浏览器会把上次 Ajax 调用返回的数据原封不动的倾倒出来,这可能是 javascript 代码,可能是未处理的 json 数据。一个成熟的网站不会出现这样的情况,因为开发人员已经用各种方法做了处理(后面讨论)。不过你如何在两天前的晚上访问 codecampo.com,有可能会看到这种情况,因为那时候我还不懂怎么处理。: )

    1.3 目标

     

    理想中应该让 Ajax 调用达到这样的状态:

    如果 Ajax 调用后的页面逻辑上已经跟之前不是同一个页面,那么 URL 应该随之改变。

    前提同上,那么在新页面点击浏览器的后退按钮,应该回到 Ajax 调用前的页面。

    状态 1 是为了让访客可以将当前网页放入收藏夹,或者通过复制粘贴 URL 分享资源地址;状态 2 是为了符合最小惊讶。

    2. 当前主流 - 只改变 URL Hash 的单页面应用

     

    仔细观察可以发现,现在的 Twitter,Google,Facebook 的 URL 地址充斥着 #号或者 #! 号。例如一个新版 Twitter 地址是这样的

    https://twitter.com/#!/chloerei 

    这个 #! 号有什么意义呢?这个可以看看阮一峰整理的这篇《URL的井号》。这里假设你已经了解 # 号后面的改变不会导致页面加载,怎么利用这个特性达到 1.3 提出的目标。

    2.1 第一步,有关 Ajax 调用的链接全部用 #path 作为链接目标

     

    例如,如果一个链接本来是

    <a href="/topics/1">topic1</a> 

    就修改为

    <a href="#/topics/1">topic1</a> 

    显然,如果不做后续工作的话,这个链接点击后页面不会发生什么变化,用户也不会被带到新地址。唯一的改变是 URL 的 # 号部分变成了 #topics/1

    2.2 设置 onhashchange 事件

     

    在 javascript api 中,窗口 window 对象的 hash 值(# 号后面部分)发生变化时,会调用 onhashchange 事件。给 onhashchange 挂上一个 function,就可以在 hash 有改动的时候调用这个 function。

    例如可以在控制台输入这段 js 代码测试

    window.onhashchange = function(){alert(window.location.hash)}

    实际中 function 里面就是放置真正用来刷新页面的代码了。比如在 jQuery 里用 $.get(location.path)。

    2.3 效果

     

    现在的 twitter,gooogle,facebook 都是使用这种方法刷新页面,这对浏览器书签、后退的支持也很好。

    但是这有一些副作用。

    一是因为页面路径被写在了 Hash 里面,而浏览器是不向服务器发送 Hash 部分的。所以打开这样的 URL 需要两个来回:1、打开空白的首页 2、根据 Hash 用 Ajax 载入实际内容

    二是把路径写在了 Hash 里面破坏了 URL 原先的含义。从 URL 字面看

    https://twitter.com/#!/chloerei 

    这个页面表示的是 twitter.com 页面上的 !/chloerie 锚点。但从实际内容上,这表示的是 chloerei 的个人页面。所以有人称这种站点为“单页面应用”。总的来说,这个方案对主流浏览器的支持程度很高,是目前的主流方案。

    3. 未来方案:基于 history.pushState API

     

    先看现实中的例子:Github。Github 的源码浏览页面是借助 Ajax,并且正常改变 URL 的例子,浏览器后退功能也正常工作。你可以在 https://github.com/chloerei/campo 点击各个文件夹,同时观察地址栏。不过目前只支持对 HTML5 友好的浏览器,比如 chrome, firefox4。

    Github 有篇简短的日志描述了他们的实现方法:https://github.com/blog/760-the-tree-slider

    下面再逐步分析一下。

    3.1 改变 URL 但不载入页面的方法

     

    HTML5 中新增了 history.pushState 方法,用以向浏览器添加历史记录,但是不触发页面载入。详细的文档可以看这里。

    基本用法就是在 Ajax 发送的同时,将访问的地址用 pushState 方法加入页面历史。如果你用 Rails 的 ujs-jquery 方式调用 Ajax,看起来是这样的(campo项目的部分代码)

    HTML 部分

    <div class="paginate"><a href="/?page=1" data-remote="true">下一页</a></div> 

    data-remote 属性是 ujs 用来启用 ajax 的标志位。

    js 部分

    $('.paginate a').live('ajax:beforeSend', function(event, xhr, settings) {   if (history && history.pushState) {

        history.pushState(null, document.title, this.href);

      }

    });

    这个钩子方法,在发送 ajax 请求之前把目标地址推进浏览器的历史记录,于是浏览器的地址栏更新但不重载整个页面。

    3.2 处理后退按钮

     

    浏览器后退的时候会触发 onpopstate 事件,所以要给这个事件挂上处理方法。

    if (history && history.pushState) {

      $(window).bind("popstate", function() {     $.getScript(location.href);

      });

    }

    这里的逻辑跟URL Hash 的单页面应用的方法很类似,不同的是之前处理的是 hashchange,这里处理的是 popstate。

    3.3 从非 Ajax 页面返回到 Ajax 页面

     

    做完上面两步,已经可以在 Ajax 页面来回切换了,但是如果进入了一个非 Ajax 页面,然后按了后退,这时候就会把之前 Ajax 获取的代码全部倒出来,因为上下文已经切换了,浏览器不知道怎么处理这些代码。

    这时候要做两个处理

    1)要求 Ajax 相关页面不缓存,如果你用 Rails,你可以看这篇文章: http://blog.serendeputy.com/posts/how-to-prevent-browsers-from-caching-a-page-in-rails/

    2)处理 popstate 的方法增加一个标志位,第一次载入页面的时候不要调用后面的逻辑。

    if (history && history.pushState) {

      var loaded = false;

      $(window).bind("popstate", function() {     if (!loaded) {

          loaded = true;

        } else {

          $.getScript(location.href);

        }

      });

    }

    注意 loaded 这个变量的作用。因为之前已经把页面缓存关了,如果不设置这个标志位,浏览器后退的时候就会既载入页面,也触发 popstate 事件,导致二次载入。

     

     

    第二段

    history.pushState/replaceState 方法

     

    熟悉JavaScript开发的同学,对History肯定不会陌生,其中最经典的方法就是go,通过第一个类型为整数的传输参数,可以使浏览器到达当前页面之前或之后,曾经浏览过的页面。当然,这个也是要刷新来实现的。

    现在History API新增了两个方法,分别是pushState和replaceState,其实用法都一样,看Mozilla的文档也没看到它们有多大不同,哈哈。

    用法如下:

    var state = { //这里可以是你想给浏览器的一个State对象,为后面的StateEvent做准备。

    title : "HTML 5 History API simple demo",

    url : "yourpage"

    };

    history.pushState(state, "HTML 5 History API simple demo", "yourpage");

    还算简单吧,那么replaceState也是同样的用法:

    var state = { //这里可以是你想给浏览器的一个State对象,为后面的StateEvent做准备。

    title : "HTML 5 History API simple demo",

    url : "yourpage"

    };

    history.replaceState(state, "HTML 5 History API simple demo", "yourpage");

    State Event

    既然有无刷新改变URL的方法,当然也要有响应这个改变的时间啦。

    嗯,没错。就有一个popstate事件,而传入的handler函数有一个参数,就是之前在pushState的第一个参数,一个State obj。开发者可以通过这个State obj来识别行为。详细代码如下:

    var state = { //这里可以是你想给浏览器的一个State对象,为后面的StateEvent做准备。

    title : "HTML 5 History API simple demo",

    url : "yourpage"

    };

    history.pushState(state, "HTML 5 History API simple demo", "yourpage");

    window.onpopstate = function (e) { document.title = e.state.title;}

    当然还可以这样:

    var state = { //这里可以是你想给浏览器的一个State对象,为后面的StateEvent做准备。

    action : "page",

    title : "HTML 5 History API simple demo",

    url : "yourpage"

    };

    history.pushState(state, "HTML 5 History API simple demo", "yourpage");

    window.onpopstate = function (e) {

    switch (e.state.action) {

    case "home" :

    document.title = "HOME ……";

    $.get("index.php").done(function (data) { 

    $("#wrapper").html(data); 

    });

    break;

    case "page" :

    document.title = e.state.title;

    $.get(e.state.url).done(function (data) { 

    $("#wrapper").html(data); 

    });

    break;

    }

  • 相关阅读:
    放大镜
    右击地图功能(全图和另存为)
    将oracle数据库中的地图属性导出.shp地图
    arcmap地图与mapinfo地图的转换
    HTML播放多媒体标签embed的详解
    小菜的系统框架界面设计你的评估是我的决策
    小菜的系统框架界面设计界面布局决定系统设计的成败
    小菜的系统框架界面设计序言
    小菜的系统框架界面设计从认知心理学谈优秀的系统界面设计?
    小菜的项目管理修炼之道
  • 原文地址:https://www.cnblogs.com/papajia/p/4498286.html
Copyright © 2011-2022 走看看