
class EventBus{
events = {}
on(event, cb){
let cbs = this.events[event] || [];
this.events[event] = [...cbs, cb]
}
off(event, cb){
let cbs = this.events[event] || [];
let index = cbs.indexOf(cb);
if (index !== -1){
this.events[event].splice(index, 1);
}
}
emit(event){
let cbs = this.events[event] || [];
cbs.forEach(cb=>cb())
}
}
--------------------------------------------------------------------------
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SPA的原生实现</title>
</head>
<body>
<!-- 导航区域 -->
<div class="router_box">
<a href="/home" class="router" replace="true">主页</a>
<a href="/news" class="router">新闻</a>
<a href="/team" class="router">团队</a>
<a href="/about100" class="router">关于</a>
</div>
<!-- 路由区域 -->
<div id="router-view"></div>
<script src='./EventBus.js'></script>
<script>
let event = new EventBus();
function Router(options){
this.mode = options.mode || 'hash';
this.routes = options.routes || [];
this.init = function(){
var eles = document.querySelectorAll('.router');
var that = this;
[...eles].forEach(item=>{
item.addEventListener('click', function(e){
e.stopPropagation();
e.preventDefault();
var path = e.target.getAttribute('href');
var isReplace = e.target.getAttribute('replace');
console.log('path...', path, isReplace);
if (that.mode == 'hash'){
if (isReplace){
let index = window.location.href.indexOf('#');
window.location.replace(`${window.location.href.slice(0, index)}#${path}`);
}else{
window.location.hash = `#${path}`;
}
}else{
if (isReplace){
window.history.replaceState('', '', path);
}else{
window.history.pushState('', '', path);
}
event.emit('popstate');
}
})
})
// 监听相关事件
if (this.mode === 'hash'){
window.addEventListener('hashchange', this.routeChange.bind(this))
}else{
window.addEventListener('popstate', this.routeChange.bind(this))
event.on('popstate', this.routeChange.bind(this));
}
// 初始化routeChange
this.routeChange();
}
// 响应路由变化
this.routeChange = function(){
let routerView = document.querySelector('#router-view');
console.log('routeChange...');
if (this.mode === 'hash'){
let path = window.location.hash.slice(1);
let index = this.routes.findIndex(item=>item.path === path);
if (index !== -1){
routerView.innerHTML = this.routes[index].component;
}else{
let matchAllIndex = this.routes.findIndex(item=>item.path === '*')
if (matchAllIndex !== -1){
let index = window.location.href.indexOf('#');
window.location.replace(`${window.location.href.slice(0, index)}#${this.routes[matchAllIndex].redirect}`);
}
}
}else{
let path = window.location.pathname;
let index = this.routes.findIndex(item=>item.path === path);
if (index !== -1){
routerView.innerHTML = this.routes[index].component;
}else{
let matchAllIndex = this.routes.findIndex(item=>item.path === '*')
if (matchAllIndex !== -1){
let index = window.location.href.indexOf('#');
window.history.replaceState('', '', this.routes[matchAllIndex].redirect);
}
}
}
}
this.init();
}
new Router({
mode: 'hash',
routes:[
{ path: '/home', component: '<h1>主页</h1><h4>新一代前端工程师:我们啥都会</h4>' },
{ path: '/news', component: '<h1>新闻</h1><h4>今天2018-11-5,上课还得穿工装</h4>' },
{ path: '/team', component: '<h1>团队</h1><h4>WEB前端工程师</h4>' },
{ path: '/about', component: '<h1>关于</h1><h4>一面而高薪就业</h4>' },
{ path:'*', redirect:'/home'}
]
})
</script>
</body>
</html>