目前来说,无论是vue,还是react,spa的路由实现方式无非就是以下两者
1.hash方式。 使用location.hash和hashchange事件实现路由
2.history api。使用html5的history api实现,主要就是popState事件等。
hash用的还是比较多的,但是这种方式的url会比较丑陋,会出现 #; 而history api就可以很好的解决这个问题,但是需要后端配置,并且由于是html5中的api,所以兼容性还不是很好
路由实现之hash
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>router</title>
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0;
}
div.router-wrap {
width: 100%;
height: 100%;
background: #fefefe;
}
a {
padding: 10px;
color: pink;
font-size: 25px;
font-weight: bold;
text-decoration: none;
}
</style>
</head>
<body>
<div class="router-wrap">
<a href="#/black">黑色</a><br>
<a href="#/green">绿色</a><br>
<a href="#/red">红色</a>
</div>
<script>
// 创建Router构造函数
// currentHash为当前hash值,routes为路径对象
function Router() {
this.currentHash = '/';
this.routes = {};
}
// 注册路径,每个路径对应一个回调函数。
Router.prototype.route = function(path, callback) {
this.routes[path] = callback || function() {
alert('未定义回调函数!');
}
}
// 更新页面函数
Router.prototype.refresh = function() {
this.currentHash = location.hash.slice(1) || '/';
this.routes[this.currentHash]();
}
// 初始化
Router.prototype.init = function() {
var self = this;
window.addEventListener('load', function() {
self.refresh();
}, false);
window.addEventListener('hashchange', function() {
self.refresh();
});
}
</script>
<script>
var wrap = document.querySelector('.router-wrap');
window.Router = new Router();
Router.route('/', function() {
wrap.style.backgroundColor = '#fefefe';
});
Router.route('/black', function() {
wrap.style.backgroundColor = 'black';
});
Router.route('/green', function() {
wrap.style.backgroundColor = 'green';
});
Router.route('/red', function() {
wrap.style.backgroundColor = 'red';
});
Router.init();
</script>
</body>
</html>
路由实现之history API
html5中的history api包括两个方法history.pushState()和history.replaceState(),包含一个事件history.onpopstate。参考MDN
1044137-20170824080502933-232401939.png注意:因为pushState的url和当前的Url必须是同源的,而file://的形式是不存在同源的说法的,所以我们必须用http://localhost的方式。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>router</title>
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0;
}
div.router-wrap {
width: 100%;
height: 100%;
background: #efefef;
}
a {
display: inline-block;
padding: 10px;
color: pink;
font-size: 25px;
font-weight: bold;
text-decoration: none;
}
</style>
</head>
<body>
<div class="router-wrap">
<a href="/black" class="history-link">黑色</a><br>
<a href="/green" class="history-link">绿色</a><br>
<a href="/red" class="history-link">红色</a>
</div>
<script>
// 创建Router构造函数
function Router() {
this.currentRoute = '';
this.routes = {};
this.init();
}
// 注册路由函数
Router.prototype.route = function(path, callback) {
// 根据type类型,选择相应的history api。
this.routes[path] = function(type) {
if(type == 1) {
history.pushState({
path: path
}, '', path);
} else if(type == 2) {
history.replaceState({
path: path
}, '', path);
}
callback();
}
}
// 更新页面
Router.prototype.refresh = function(path, type) {
this.routes[path](type);
}
// 初始化
Router.prototype.init = function() {
var self = this;
// 重新加载函数,这里使用的主机是http://localhost:8088/
window.addEventListener('load', function() {
self.currentRoute = location.href.slice(location.href.indexOf('/', 8));
console.log(self.currentRoute);
self.refresh(self.currentRoute);
});
// 当用户点击前进后退按钮时触发函数
window.addEventListener('popstate', function() {
console.log('history.state.path:', history.state.path);
self.currentRoute = history.state.path;
self.refresh(self.currentRoute, 2);
}, false);
// 对所有的link标签进行绑定事件
var historyLinks = document.querySelectorAll('.history-link');
for(var i = 0, len = historyLinks.length; i < len; i++) {
historyLinks[i].onclick = function(e) {
// 阻止默认
e.preventDefault();
self.currentRoute = e.target.getAttribute('href');
self.refresh(self.currentRoute, 1);
}
}
}
</script>
<script>
var wrap = document.querySelector('.router-wrap');
// 实例化Router
window.Router = new Router();
// 注册路由,实现相应功能
Router.route('/', function() {
wrap.style.backgroundColor = '#efefef'
});
Router.route('/black', function() {
wrap.style.backgroundColor = 'black';
});
Router.route('/green', function() {
wrap.style.backgroundColor = 'green';
});
Router.route('/red', function() {
wrap.style.backgroundColor = 'red';
});
</script>
</body>
</html>
网友评论