JS单页面路由的实现
对于页面路由的实现是每个项目都必须做到的一点,在之前很多都是服务端渲染好返回html页面给浏览器,这样就不用前端去操作了,与此同时在html页面上也可以嵌套后端语言。这种也称为前后端不分离混合开发。但是服务器端压力越来越大。而且有一个最大的弊端就是路由的调转需要刷新页面,那么响应时间也就增长了。后来ajax异步刷新的出现使得前端也可以对url进行管理,此时,前端路由就出现了,像最近火爆的Vue, React,Angular等。
单页面路由实现的原理:这里我们采用hash路由方式,让window绑定监听函数,当url的hash值发生变化的时候会触发hashchange,load回调,在回调中进行不同的操作,马上刷新页面,从而显示不同的页面。
采用iframe作为路由子页面
HTML代码
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
<style type="text/css">
.slide{
width: 100px;
}
.slide li{
height: 50px;
}
.slide li.active{
background: red;
color: #ffffff;
}
</style>
</head>
<body>
<div class="box">
<ul class="slide">
<li><a class="li1" data-url="a.html" data-href="#/" href="javascript:;">turn white</a></li>
<li><a class="li2" data-url="b.html" data-href="#/blue" href="javascript:;">turn blue</a></li>
<li><a class="li3" data-url="c.html" data-href="#/green?id=12&name='tom'" href="javascript:;">turn green</a></li>
</ul>
</div>
<div class="iframe-box">
<iframe class="iframe" name="myFrame" src="a.html"></iframe>
</div>
</body>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script type="text/javascript">
class Routers {
constructor() {
this.routes = {};
this.currentUrl = '';
}
route(path, callback) {
this.routes[path] = callback || function(){};
console.log(this.routes)
}
refresh() {
var path = location.hash.slice(1) || '/';
var hash,query = {};
if (path.indexOf("?") != -1) {
hash = path.split("?")[0]
path.split("?")[1].split("&").forEach(item => {
query[item.split("=")[0]] = item.split("=")[1]
})
} else {
hash = path
}
this.currentUrl = hash;
this.routes[this.currentUrl]({
path: hash,
query: query
});
}
init() {
window.addEventListener('load', this.refresh.bind(this), false);
window.addEventListener('hashchange', this.refresh.bind(this), false);
}
}
window.Router = new Routers();
window.Router.init();
// change Page anything
$(".slide li a").click(function() {
var isHref = true // 控制是否阻止(这里写死一个值demo),这个值可以用缓存来做,这样我觉得就可以子父页面共用了
var href = $(this).data("href");
console.log(href)
if (isHref) {
window.location.href = href
} else {
//这里就是没跳转逻辑了
// 如果是子页面弹出 确定要离开?弹窗的话,就用之前那个父调子页面方法
myFrame.window.childfunction();
}
})
function changeFun() {
$(this).parent().addClass("active");
$(this).parent().siblings().removeClass("active");
$('.iframe-box').empty();
$(".iframe-box").append(`<iframe class="iframe" src="${$(this).data("url")}"></iframe>`);
}
Router.route('/', function() {
// 方法一
// $(".li1").click(changeFun)
// $(".li1").click()
// $(".li1").off('click');
// 方法二
$(".li1").parent().addClass("active");
$(".li1").parent().siblings().removeClass("active")
$('.iframe-box').empty();
$(".iframe-box").append(`<iframe class="iframe" name="myFrame" src="a.html"></iframe>`)
});
Router.route('/blue', function() {
// $(".li2").click(changeFun)
// $(".li2").click()
// $(".li2").off('click');
$(".li2").parent().addClass("active");
$(".li2").parent().siblings().removeClass("active")
$('.iframe-box').empty();
$(".iframe-box").append(`<iframe class="iframe" name="myFrame2" src="b.html"></iframe>`)
});
Router.route('/green', function(res) {
// $(".li3").click(changeFun)
// $(".li3").click()
// $(".li3").off('click');
$(".li3").parent().addClass("active");
$(".li3").parent().siblings().removeClass("active")
$('.iframe-box').empty();
$(".iframe-box").append(`<iframe class="iframe" name="myFrame3" src="c.html"></iframe>`)
});
</script>
</html>
主要思路:
1…init监听浏览器url的hash值更新事件,利用window.addEventListener的监听发放监听页面加载load和hash改变hashchange事件执行回调函数
2.route存储路由更新时的回调到回调数组routes中,回掉函数将负责对页面进行更新。
3.refresh执行当前url的回调函数,更新页面。