Hash 路由
一、认识
Hash
模式 在浏览器中符号#
,#
以及 #
后面的字符称之为 hash
。用 window.location.hash
读取。hash
虽然在 URL
中,但不被包括在 HTTP
请求中; 用来指导浏览器动作,对服务端安全无用,hash
不会重加载页面
二、思路
-
URL
中的hash
值只是客户端的一种状态,向服务端发送请求的时候,hash
部分不会被发送。 -
hash
值得改变会在浏览器的历史记增加访问记录,所以可以通过浏览器的回退、前进控制hash
值的改变。 -
可以通过
a
标签设置href
值或者通过js
给location.hash
赋值来改变hash
值。 -
可以通过
hashchang
事件来监听hash
值的变化,从而对页面进行跳转(渲染)。
三、实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Hash 路由</title>
</head>
<body>
<div id="root"></div>
<div id="router-container">
<a href="#/home">首页</a>
<a href="#/about">关于</a>
<a href="#/contact">联系</a>
</div>
<script>
class HashRouter {
constructor() {
this.routes = {};
this.currentUrl = "";
this.container = document.getElementById("root");
this.init();
}
init() {
window.addEventListener("load", this.refresh.bind(this), false);
window.addEventListener("hashchange", this.refresh.bind(this), false);
}
route(path, callback) {
this.routes[path] = callback || function () {};
}
refresh() {
this.currentUrl = location.hash.slice(1) || "/";
this.routes[this.currentUrl]?.();
}
render(html) {
this.container.innerHTML = html;
}
push(path) {
location.hash = path;
}
}
const router = new HashRouter();
router.route("/", () => {
router.render("<h1>首页</h1>");
});
router.route("/home", () => {
router.render("<h1>首页</h1>");
});
router.route("/about", () => {
router.render("<h1>关于</h1>");
});
router.route("/contact", () => {
router.render("<h1>联系</h1>");
});
</script>
</body>
</html>
四、问题
4.1 Hash
模式 与 History
模式的区别?
表现上: hash
模式 url
里面永远带着#号,开发当中默认使用这个模式。如果用户考虑url
的规范那么就需要使用history
模式,因为history
模式没有#
号,是个正常的url
,适合推广宣传;
行为上: 使用 history
模式还有一个问题就是,在访问二级页面的时候,做刷新操作,会出现404
错误,那么就需要和后端人配合,让他配置一下 apache
或是 nginx
的url
重定向,重定向到你的首页路由上就ok了
调用方法上: 调用 history.pushState()
相比于直接修改 hash
,存在以下优势:
-
pushState()
设置的新URL
可以是与当前URL
同源的任意URL
; 而hash
只可修改#
后面的部分,因此只能设置与当前URL
同文档的URL
-
pushState()
设置的新URL
可以与当前URL
一模一样,这样也会把记录添加到栈中;hash
设置的新值必须与原来不一样才会触发动作将记录添加到栈中 -
pushState()
通过stateObject
参数可以添加任意类型的数据到记录中; 而hash
只可添加短字符串pushState()
可额外设置title
属性供后续使用