1.hash路由实现
1. hash路由改变不会触发浏览器刷新, 会触发相应的hashchange事件
<!DOCTYPE html>
<html lang="en">
<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">
<title>Document</title>
</head>
<body>
<div>
<a href="#/">/</a>
<a href="#/about">/about</a>
<a href="#/hello">/hello</a>
<div class="content"></div>
</div>
<script>
class Router{
constructor() {
this.routes = {};
this.currentUrl = '';
this.initListener();
}
push(path, callback) {
this.routes[path] = callback || function() {}
}
updateView() {
this.currentUrl = location.hash.slice(1) || '/';
this.routes[this.currentUrl] && this.routes[this.currentUrl]();
}
initListener() {
window.addEventListener('load', this.updateView.bind(this), false)
window.addEventListener('hashchange', this.updateView.bind(this), false)
}
}
const router = new Router();
router.push('/', function() {
document.querySelector('.content').innerHTML = 'Home'
})
router.push('/hello', function() {
document.querySelector('.content').innerHTML = 'hello'
})
router.push('/about', function() {
document.querySelector('.content').innerHTML = 'about'
})
</script>
</body>
</html>
2. history路由实现
History 路由是基于 HTML5 规范,在 HTML5 规范中提供了 history.pushState || history.replaceState 来进行路由控制。
使用history.pushState({}, null, ‘/home’)时候, 页面不会刷新,pushState会有页面记录,replaceState不会有
pushState方法说明
- state:存储 JSON 字符串,可以用在 popstate 事件中
- title:现在大多浏览器忽略这个参数,直接用 null 代替
- url:任意有效的 URL,用于更新浏览器的地址栏
<!DOCTYPE html>
<html lang="en">
<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">
<title>Document</title>
</head>
<body>
<div>
<a data-href="/" href="#">/</a>
<a data-href="/about" href="#">/about</a>
<a data-href="/hello" href="#">/hello</a>
</div>
<script>
class Router {
constructor() {
this.routes = {};
this.currentUrl = '';
this.initListener();
this.initBindLink();
}
push(path, callback) {
this.routes[path] = callback || function () { };
}
updateView(url) {
this.currentUrl = url;
this.routes[this.currentUrl] && this.routes[this.currentUrl]();
}
initBindLink() {
const allLink = document.querySelectorAll('a[data-href]');
for (let i = 0, len = allLink.length; i < len; i++) {
const current = allLink[i];
current.addEventListener(
'click',
e => {
e.preventDefault();
const url = current.getAttribute('data-href');
history.pushState({}, null, url);
this.updateView(url);
},
false
);
}
}
initListener() {
window.addEventListener('popstate', () => this.updateView(window.location.pathname));
window.addEventListener('load', () => this.updateView('/'), false);
}
}
const router = new Router();
router.push('/', function () {
document.querySelector('.content').innerHTML = 'Home'
})
router.push('/hello', function () {
document.querySelector('.content').innerHTML = 'hello'
})
router.push('/about', function () {
document.querySelector('.content').innerHTML = 'about'
})
</script>
</body>
</html>