一文读懂前端路由模式hash

HTML中的hash(#号)


(1)、#的含义
“#”代表网页中的一个位置,右面的字符就是代表的位置信息。

http://www.example.com/index.html#first

上述含义:代表网页index.html的first位置,浏览器读取这个URL后,会自动将first位置滚动至可视区域。

两种网页制定标识符:

1、使用锚点
<a name="print"></a>

2、使用id属性
<div id="print" ></div>

(2)、HTTP请求不包括#
意味着它不管怎么变化都不会影响请求URL,即它只针对浏览器的。

浏览器请求:http://www.example.com/index.html#first

服务器收到:http://www.example.com/index.html
》》实际发出的请求 GET  /index.html   HTTP/1.1    不包含#first

(3)、#后的字符,特殊需转码
在第一个#后面出现的任何字符,都会被浏览器解读为位置标识符。这意味着,这些字符都不会被发送到服务器端。如果需要发送需要先转码。

浏览器请求:http://www.example.com/index.html?color=#fff
》》原意是指定一个颜色值

服务器收到:http://www.example.com/index.html?color=
》》实际发出的请求
GET  /index.html?color=   HTTP/1.1
Host:www.example.com
》》"#fff"被省略了

注意:如果发送需要转码,将#转码为%23,浏览器才会将其作为实义字符处理

浏览器请求:http://www.example.com/index.html?color=%23fff

服务器收到:http://www.example.com/index.html?color=%23fff

(4)、改变#不触发网页重载
意味着单单改变#后的部分,浏览器只会滚动到相应位置,不会重新加载网页。

从
http://www.example.com/index.html#location1
改成
http://www.example.com/index.html#location2
浏览器不会重新向服务器请求index.html

(5)、改变#会改变浏览器的访问历史

  • 每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用”后退”按钮,就可以回到上一个位置。
  • 在ajax应用程序中,可以用不同的#值,表示不同的访问状态,然后向用户给出可以访问某个状态的链接。
  • 注意:上述规则对IE6和IE7不成立,它们不会因为#的改变而增加历史记录。

(6)、window.location.hash读取#值
window.location.hash这个属性可读可写。读取时,可以用来判断网页状态是否改变;写入时,则会在不重载网页的前提下,创造一条访问历史记录。

(7)、onhashchange事件
这是一个HTML 5新增的事件,当#值发生变化时,就会触发这个事件。IE8+、Firefox 3.6+、Chrome 5+、Safari 4.0+支持该事件。

// 它的使用方法有三种:
window.onhashchange = func;

<body οnhashchange="func();">

window.addEventListener("hashchange", func,  false);

注意:对于不支持onhashchange的浏览器,可以用setInterval监控location.hash的变化。

(8)Google抓取#的机制
默认情况下,Google的网络蜘蛛忽视URL的#部分。但是,Google还规定,如果你希望Ajax生成的内容被浏览引擎读取,那么URL中可以使用”#!”,Google会自动将其后面的内容转成查询字符串escaped_fragment的值。

// 比如,Google发现新版twitter的URL如下:
http://twitter.com/#!/username
// 就会自动抓取另一个URL:
http://twitter.com/?_escaped_fragment_=/username
// 通过这种机制,Google就可以索引动态的Ajax内容。

Hash思路


(1)首次进入触发 DOMContentLoaded事件,解析路由,渲染视图
(2)URL标识符发生变更时,将触发hashchange事件 (跟在#符号后面的URL部分,包括#符号),解析路由,渲染视图,路由跳转。

Demo示例

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <meta http-equiv="X-UA-Compatible" content="ie=edge"/>
    <title>Document</title>
  </head>
  <body>
    <ul>
      <li>
        <a href="#/a">a</a>
      </li>
      <li>
        <a href="#/b">b</a>
      </li>
      <li>
        <a href="#/c">c</a>
      </li>
    </ul>
    <div id="view"></div>

    <script>
      var view = null;

      // (1)首次进入:页面加载完不会触发 hashchange,
      // 这里主动触发一次 hashchange 事件,该事件快于onLoad,所以需要在这里操作
      window.addEventListener('DOMContentLoaded', function () {
        view = document.querySelector('#view');
        viewChange();
      });

      // (1)监听路由变化
      window.addEventListener('hashchange', viewChange);

      // 渲染视图
      function viewChange() {
        switch (location.hash) {
          case '#/b':
            view.innerHTML = 'b';
            break;
          case '#/c':
            view.innerHTML = 'c';
            break;
          default:
            view.innerHTML = 'a';
            break;
        }
      }
    </script>
  </body>
</html>
标签: