(。・∀・)ノ゙嗨
我们经常在 url 中看到 #,这个 # 有两种情况,一个是我们所谓的锚点,比如典型的回到顶部按钮原理、Github 上各个标题之间的跳转等,路由里的 # 不叫锚点,我们称之为 hash(哈希),大型框架的路由系统大多都是hash实现的。
刚看完上面那段话,可能有人会有疑问:URL中的#是什么,如何用hash实现前端路由呢?
别着急,往下看 φ(゜▽゜*)♪~~~
首先我们来说一下URL中的井号(其实也叫 hash)
URL中的hash(井号)
1.#的含义
#代表网页中的一个位置,其右边的字符,就是该位置的标识符。比如
http://www.example.com/index.html#print
就是代表index.html中的print位置。浏览器会自动把print位置滚动到页面可视区域内。
设置方法:
step1:设置一个锚点<a href="#print">
定位到print位置
step2:在页面需要定位的内容加上id="print"
。例如:<div id="print"></div>
测试:step1设置的锚点,step2中id为print的内容会滚动到页面顶端(可观察滚动条的距离)。同时,页面的url末端中会出现#print的哈希值。
2.HTTP请求不包含#
#号是用来指导浏览器动作的,对服务器端完全无用。所以,HTTP请求中不包含#。
比如,访问下面的网址:
http://jquery.com#hello
浏览器实际发出的请求时这样的:
可以看到,只是请求了http://jquery.com
,没有请求"#hello"的部分。
3.#后面的字符
在第一个#后面出现的任何字符,都 会被浏览器解读为位置标识符。这意味着,这些字符都不会被发送到服务器端
。
比如,下面的URL的原意是指定一个颜色值:
http://jquery.com/?color=#fff
但是浏览器实际发出的请求是:
可以看到,"#fff"被省略了。只有将#转码为%23,浏览器才会将其作为实义字符处理。也就是说,上面的网址应该被写成:
http://jquery.com/?color=%23fff
4.改变#不触发网页重载
单单改变#后的内容,浏览器只会滚动到相应位置,不会重新加载网页。
浏览器不会重新向服务器请求页面。
5.改变#会改变浏览器的访问历史
每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用"后退"按钮,就可以回到上一个位置。
这对于ajax应用程序特别有用,可以用不同的#值,表示不同的访问状态,然后向用户给出可以访问某个状态的链接。
(值得注意的是,上述规则对IE 6和IE 7不成立,它们不会因为#的改变而增加历史记录。)
6.window.location.hash
读取#值
window.location.hash 这个属性可读可写。读取时,可以用来判断网页状态是否改变;写入时,则会在不重载网页的前提下,创造一条访问历史记录。
7.onhashchange
事件
这是一个HTML 5新增的事件,当#值发生变化时,就会触发这个事件。IE8+、Firefox 3.6+、Chrome 5+、Safari 4.0+支持该事件。
它的使用方法有三种:
1.window.onhashchange = func;
2.<body onhashchange="func();">
3.window.addEventListener("hashchange", func, false);
了解了hash的基本概念后,我们再来解决下一个问题,如何用它实现前端路由
~~( ̄▽ ̄)~*
首先我们需要使用一个可以根据监听哈希变化触发的事件 —— hashchange 事件。
我们用 window.location 处理哈希的改变时不会重新渲染页面,而是当作新页面加到历史记录中,这样我们跳转页面就可以在 hashchange 事件中注册 ajax 从而改变页面内容。
下面是一个用hash实现前端路由的栗子:
<!DOCTYPE html>
<html lang="zh">
<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">
<style>
li {
display: inline-block;
margin: 0 30px 30px 0;
}
</style>
<title></title>
</head>
<body>
<ul>
<li><a href="#/" class="">turn white</a></li>
<li><a href="#/orange" class="">turn orange</a></li>
<li><a href="#/purple=123" class="">turn purple</a></li>
</ul>
</body>
<script>
function Router() { //这是一个对象 对象格式{/: ƒ, /orange: ƒ, /purple=123: ƒ}
this.routes = {};
this.currentUrl = '';
}
//在Router.prototype原型上设置方法,第一个设置路由,第二个路由跳转,第三个页面初始化
Router.prototype.route = function(path, callback) {
this.routes[path] = callback || function() {};
console.log(this.routes)
};
Router.prototype.refresh = function() {
//console.log(location) //Location 对象Location 对象包含有关当前 URL 的信息。Location 对象是 Window 对象的一个部分,可通过 window.location 属性来访问。
//console.log(location.hash); #/purple=123
this.currentUrl = location.hash.slice(1) || '/'; //截取#后面的内容
this.routes[this.currentUrl](); //根据属性名 执行对应的函数
};
Router.prototype.init = function() {
window.addEventListener('load', this.refresh.bind(this), false); //加载首页
window.addEventListener('hashchange', this.refresh.bind(this), false); //当URL的片段标识符更改时,将触发hashchange事件
}
//自定义封装一个路由
window.Router = new Router();
window.Router.init();
var content = document.querySelector('body');
// change Page anything
function changeBgColor(color) {
content.style.backgroundColor = color;
}
Router.route('/', function() {
changeBgColor('white');
});
Router.route('/orange', function() {
changeBgColor('orange');
});
Router.route('/purple=123', function() {
changeBgColor('purple');
});
</script>
</html>
实现的效果图:
我们可以观察到点击不同的跳转按钮,对应url后面的hash也在改变。
这就是一个简单的前端路由~~
该兴趣的同学可以尝试一下 ヾ( ̄▽ ̄)ByeBye