在vue-router中有两种模式:hash模式和history模式
hash模式
hash模式:是用hash方式来模拟一个完整URL,其中URL中hash值即自带#之后值,
hash值发生变化时,页面不会重新加载,可以通过onhashchange事件来监听hash(window.location.hash)值的变化来实现更新页面需要更新内容,不需刷新页面。
模拟一个hash模式例子来加深理解,代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#nav a {
margin-right: 10px;
}
#nav a.act {
color: #FF0000;
}
</style>
</head>
<body>
<nav id="nav"></nav>
<main id="app"></main>
<script>
class Router {
constructor() {
this.navs = [{
path: "#index",
title: "首页",
content: "首页-内容"
}, {
path: "#news",
title: "新闻",
content: "新闻-内容"
}, {
path: "#about",
title: "关于",
content: "关于-内容"
}]
this.navNode = document.getElementById("nav");
this.el = document.getElementById("app");
}
init() {
this.createNav();
this.haddleHashChage();
//监听hash值变动
window.addEventListener("hashchange", this.haddleHashChage.bind(this));
}
createNav() {//创建导航
let fragment = document.createDocumentFragment();
this.navs.forEach(nav => {
let tagA = document.createElement("a");
tagA.href = nav.path;
tagA.innerText = nav.title;
fragment.appendChild(tagA);
})
this.navNode.appendChild(fragment);
}
haddleHashChage() {//根据hash值,变动内容
const hashVal = window.location.hash || this.navs[0].path;
this.navs.forEach((nav, index) => {
let curNodes = this.navNode.childNodes[index];
curNodes.className = "";
if (nav.path == hashVal) {
curNodes.className = "act";
this.el.innerHTML = nav.content;
}
})
}
}
const router = new Router();
router.init();
</script>
</body>
</html>
history模式
若不想URL后面带#hash值,就可以采用history模式,
先了解historyAPI,链接: https://developer.mozilla.org/zh-CN/docs/Web/API/History_API.
history模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。
是利用history.pushState(添加一条历史记录)来更改 URL 跳转而无须重新加载页面,当页面前进后退,意味着历史记录项发生变化了,就会onpopstate事件,监听页面需要更新内容,不需刷新页面。
模拟一个history模式例子来加深理解,代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#nav a {
margin-right: 10px;
}
#nav a.act {
color: #FF0000;
}
</style>
</head>
<body>
<nav id="nav"></nav>
<main id="app"></main>
<script>
class Router {
constructor() {
this.navs = [{
path: "?page=index",
title: "首页",
content: "首页-内容"
}, {
path: "?page=news",
title: "新闻",
content: "新闻-内容"
}, {
path: "?page=about",
title: "关于",
content: "关于-内容"
}];
this.navNode = document.getElementById("nav");
this.el = document.getElementById("app");
this.curPage = "";
}
init() {
this.createNav();
this.haddleNav();
this.haddlePopstate();
window.addEventListener("popstate", this.haddlePopstate.bind(this))
}
createNav() {//创建导航
let fragment = document.createDocumentFragment();
this.navs.forEach(nav => {
let tagA = document.createElement("a");
tagA.href = nav.path;
tagA.setAttribute("data-page", nav.path);
tagA.innerText = nav.title;
fragment.appendChild(tagA);
})
this.navNode.appendChild(fragment);
}
haddleNav() {//点击导航
this.navNode.addEventListener("click", function (evt) {
evt.preventDefault();
let target = evt.target;
if (target.nodeName == "A") {
this.curPage = target.getAttribute("data-page");
history.pushState("", "", this.curPage)
this.navToContent();
}
}.bind(this))
}
navToContent() {//切换内容
this.navs.forEach((nav, index) => {
let curNodes = this.navNode.childNodes[index];
curNodes.className = "";
if (nav.path == this.curPage) {
curNodes.className = "act";
this.el.innerHTML = nav.content;
}
})
}
haddlePopstate() {//查询参数发生变化时
this.curPage = this.queryParams();
this.navToContent();
}
queryParams() {//查询参数
return window.location.search || this.navs[0].path;
}
}
const router = new Router();
router.init();
</script>
</body>
</html>
以上两个例子也在我的github上查看
链接: https://github.com/mina882/hash-pushState.