hash 介绍
我们在使用 Vue 或者 React 等前端渲染时,通常会有 hash 路由和 history 路由两种路由方式。
hash的优缺点
优点:
- 只需要前端配置路由表, 不需要后端的参与
- 兼容性好, 浏览器都能支持
- hash值改变不会向后端发送请求, 完全属于前端路由
缺点:
- hash值前面需要加#, 不符合url规范,也不美观
- 服务器端无法准确跟踪前端路由信息
- 与锚点定位元素的功能冲突
通过Hash实现前端路由
监听 url 中 hash 的变化,会触发hashchange
事件,我们可以在监听事件中渲染不同的内容,从而实现前端路由。
先声明个 Router
class Router {
constructor(params) {
this.cache = params.router;
this.init();
}
//初始化 添加监听浏览器hashchange 以及dom loaded函数
init() {
window.addEventListener('hashchange', () => {
this.trigger();
});
window.addEventListener('load', () => {
this.trigger();
})
};
//匹配hash对应的回调函数,并触发
trigger() {
const hash = location.hash.slice(1) || 'default';
const cache = this.cache;
for (const r in cache) {
if (cache.hasOwnProperty(r)) {
const reg = this.initRegexps(r);
if (reg.test(hash)) {
document.getElementById('app').innerHTML = cache[r]
}
}
}
};
/**
*将cache内的key 做正则处理,并返回
* 第一个正则 匹配诸如/,.+-?$#{}[]] 关键字 并在关键字前面加转译字符\
* 第二个正则 匹配() 标示()内部内容可有可无
* 第三个正则 匹配: 在/后面可以由接受任意字符,直到遇到下一个/
* 第四个正则 匹配* 在*后面可以由接受任意字符
*/
initRegexps(route) {
route = route.replace(/[/,.+\-?$#{}\[\]]/g, '\\$&')
.replace(/\((.*?)\)/g, '(?:$1)?')
.replace(/(\/\w?:\w+)+/g, '\/([^/]+)')
.replace(/\*\w*/g, '([^?]*?)');
return new RegExp('^' + route + '$');
};
//将匹配的正则返回,为回调函数提供参数
getParams(reg, hash) {
return reg.exec(hash).slice(1);
}
}
在html上
<!--菜单区域-->
<div>
<a href="#/index">index</a>
</div>
<div>
<a href="#/det">det</a>
</div>
<!--显示内容区-->
<div id="app"></div>
配置router并触发。
const router = {
"/index": '<div>index内容</div>',
"/det": '<div>det内容</div>'
}
new Router({
router,
templateId: 'app'
});