开篇日常立个flag……
最近在做一些应用,类似于单页应用,想实现类似于 Vue 路由的效果。
但是个人 Vue 基础四舍五入约等于无,而且看着 Vue-router 吃力+用不起来(因为我的项目前后端不分离,而且使用的 js 语法基本上停留在远古时代:ES5甚至更久远以前……)
之前尝试过模拟,但是模拟太痛苦了,而且一堆问题,还不好维护。
于是想着自己用原生 js 写一个简单的单页应用路由吧。
话不多说,先上效果图

gitee:https://gitee.com/chen3322275/singlepagerouter/
1、location.hash 可以修改页面的锚点
2、当前页面锚点的改变,会触发 hashchange 事件
这样,注册一个 hashchange 事件,监听 hash 的变化,切换页面指定元素的显示与隐藏,可以达到单页应用的效果。
首先我们约定一个路由对象 route,route 包含两个属性,即 id 和 handle。
接着,我们将会设定一个路由表,记录为 routes,为一个 route 对象的数组。
最后,实现一个路由器 Router 对象,还监听以及操作路由跳转。
三者的定义如下:
//route 单个路由对象
var route = { id: ‘next‘, handle: function () { console.log("切换到next");}
//routes 路由表
var routes = [{ id: ‘index‘ }, { id: ‘next‘, handle: function () { console.log("切换到next");} }]
//router 路由器
var router = new Router(routes);
注释:
route 对象的 id,除了为操作元素(一般为 div)的 id 外,还将会是 hash 的值。
handle 为一个函数,类似于回调函数,在切换该路由时执行。
若 id 为空,则隐藏路由表所有路由。
直接上代码
/*
* 模块:单页应用路由
* 作者:cls
* 日期:2021.04.17
* 使用:var routes = [{ id: ‘index‘ }, { id: ‘next‘, handle: function () { console.log("切换到next");} }]
* var router = new Router(routes);
*/
function Router(routes, defaultRoute) {
var othis = this;
//路由初始化
routes && othis.init(routes, defaultRoute);
//绑定 hashchange 事件
window.addEventListener("hashchange", function() {
let route = location.hash.slice(1) || "";
othis.oldRoute = othis.currentRoute;
othis.currentRoute = route;
othis.changePage(route);
});
}
//初始化,可多次初始化
Router.prototype.init = function(routes, defaultRoute) {
if (routes == undefined || routes.length == undefined || routes.length == 0) {
console.error("Router初始化失败:routes错误!");
return;
}
this.routes = routes;
this.currentRoute = location.hash.slice(1) || defaultRoute || routes[0].id; //当前路由获取顺序
this.oldRoute = "";
location.hash || history.replaceState(null, null, ‘#‘ + this.currentRoute); //hash为空,切换当前hash
this.changePage(this.currentRoute);
this.oldRoute = location.hash;
}
//切换路由
Router.prototype.push = function(route, callback) {
//获取route
switch (typeof(route)) {
case "string":
break;
case "undefined":
route = location.hash.slice(1) || "";
break;
case "number":
route = this.routes[route] || "";
break;
case "object":
route = route.id || "";
break;
}
location.hash = route; //切换hash,接下来的事情交给hashchange去做。如果与上一次的route一致,不会触发hashchange事件
}
//切换页面:route为字符串,为空则隐藏所有路由
Router.prototype.changePage = function(route) {
for (let i = 0; i < this.routes.length; i++) {
let e = document.getElementById(routes[i].id);
if (routes[i].id == route) {
e && (e.style.display = "block");
(typeof(routes[i].handle) === "function") && routes[i].handle(); //handle 存在,执行函数
} else {
e && (e.style.display = "none");
}
}
}
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>单页路由测试</title>
</head>
<body>
<div>
<h1>Welcome</h1>
<a href="#">空的</a>
<a href="#index">index啊啊啊</a>
<button onclick="router.push(‘next‘)">next测试</button>
<div id="index">
index啊啊啊
</div>
<div id="next">
next啊啊啊 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
</div>
</div>
<script src="~/js/site.js"></script>
<script>
//路由表
var routes = [
{ id: ‘‘ },
{ id: ‘index‘ },
{ id: ‘next‘, handle: function () { console.log("切换到next"); console.log(this); } }
]
//路由器
var router = new Router(routes, ‘index‘);
</script>
</body>
</html>
1、整个应用生命周期,只创建一次路由器,即 var router = new Router() 时,只 new 一次。(否则会注册多次 hashchange 事件)
2、路由器创建以后,可以使用 router.init() 切换路由表
3、控制 router 跳转路由使用 router.push(route) 方法,输入的 route 可以是路由表的下标,也可以是路由表 id 的字符串,也可以是 route 对象,若没有输入,则默认不会跳转。
小蚊 的 用原生js做单页应用(博文挂掉了,链接复制不到)
前端 JS 原生 javascript 和 location.hash 实现一个单页应用的路由 router
原文:https://www.cnblogs.com/clis/p/14672179.html