最近在看浏览器相关的内容,看到hash和history相关的内容了,自然而然想起来vue-router的两种模式,一直以来只知道这两种最模式最明显的区别反应在url上。
即:hash会在浏览器地址后面增加#号,hirtory可以自定义地址。
例如这个地址http://127.0.0.1:8848/es6/vue/hash.html#hello #hello这个内容就被称为hash也被成为散列值
在正式开始写一个例子之前,你需要先知道hash模式的这些特点
- hash不会随请求发送到服务器端,因此改变hash不会重载页面
- 通过window.onhashchange事件来监听hash值改变,以此来获取新的url地址和旧的url地址
- location.hash值的变化会直接反应到浏览器的地址栏,因此可以在浏览器看到
下面我们来介绍一下怎么来模拟实现一个类似Vue-router的功能:
插一嘴,后面有时间看一下vue-router源码对比实现一个vue-router,完美!
大致思路:
- 注册路由表
- 当检测到路由发生改变的时候,更新页面内容
最后实现效果就是点击按钮可以切换页面内容,通过地址栏修改hash值也可以进行页面切换。
哈哈哈,没有看错就是这么简单。。
下面看代码:
点击切换就相当于是router跳转的逻辑,不多做过多的解释。
//声明路由表
let routes = ["hello", "world"];
//保存当前hash
let currentTab;
//初始化展示hello页面
createElement("hello");
//点击切换页面
function handleClick(name) {
window.location.hash = name;
currentTab = name;
}
实现路由监听
Q:为什么不直接使用window.location.hash?
A:因为window.location中的内容是改变后的地址才能反应过来的,我们需要在地址栏改变之前就要只要需要渲染哪个页面,然后对其进行什么样的操作。
//监听hash改变事件-路由改变后页面变化
window.addEventListener("hashchange", function (e) {
let currentHash = e.newURL.split("#")[1];
let widnowHash = getHash();
//如果两个hash都不存在则return
if (!widnowHash && widnowHash) return;
//容错处理,优先取hashchange事件中的hash
currentHash ? (currentTab = currentHash) : (currentTab = getHash());
//检测路由改变后,更新页面
createElement(currentTab);
});
更新页面
Q:为什么要这么模拟?
A:我们在框架中一般是用webpack来帮我们实现这些内容的。webpack打包好的js运行出来就是一个个的页面,我们if里面判断的代码就相当于是做了这么一件事情。
//模拟单页应用替换整个#app内内容的操作
function createElement(currentTab) {
let container = document.getElementById("container");
//每次先清空container中的内容
container.innerHTML = "";
//创建标签
let ele = document.createElement("div");
ele.setAttribute("id", currentTab);
if (currentTab === "hello") {
ele.innerText = "this is hello page!!!";
} else if (currentTab === "world") {
ele.innerText = "this is world page!!!";
}
//将标签插入到container中
container.appendChild(ele);
}
参考链接:https://blog.csdn.net/Charissa2017/article/details/104779412
完整代码:
https://github.com/Cloverao/Interview/blob/master/js/hash.html