class HistoryRouter{
constructor(){
//用于存储不同path值对应的回调函数
this.routers = {};
this.listenPopState();
this.listenLink();
}
//监听popstate
listenPopState(){
window.addEventListener('popstate',(e)=>{
let state = e.state || {},
path = state.path || '';
this.dealPathHandler(path)
},false)
}
//全局监听A链接
listenLink(){
window.addEventListener('click',(e)=>{
let dom = e.target;
if(dom.tagName.toUpperCase() === 'A' && dom.getAttribute('href')){
e.preventDefault()
this.assign(dom.getAttribute('href'));
}
},false)
}
//用于首次进入页面时调用
load(){
let path = location.pathname;
this.dealPathHandler(path)
}
//用于注册每个视图
register(path,callback = function(){}){
this.routers[path] = callback;
}
//用于注册首页
registerIndex(callback = function(){}){
this.routers['/'] = callback;
}
//用于处理视图未找到的情况
registerNotFound(callback = function(){}){
this.routers['404'] = callback;
}
//用于处理异常情况
registerError(callback = function(){}){
this.routers['error'] = callback;
}
//跳转到path
assign(path){
history.pushState({path},null,path);
this.dealPathHandler(path)
}
//替换为path
replace(path){
history.replaceState({path},null,path);
this.dealPathHandler(path)
}
//通用处理 path 调用回调函数
dealPathHandler(path){
let handler;
//没有对应path
if(!this.routers.hasOwnProperty(path)){
handler = this.routers['404'] || function(){};
}
//有对应path
else{
handler = this.routers[path];
}
try{
handler.call(this)
}catch(e){
console.error(e);
(this.routers['error'] || function(){}).call(this,e);
}
}
}
1.创建一个路由对象, 实现 register 方法用于注册每个 location.pathname 值对应的回调函数
2.当 location.pathname === '/' 时,认为是首页,所以实现 registerIndex 方法用于注册首页时的回调函数
3.解决 location.path 没有对应的匹配,增加方法 registerNotFound 用于注册默认回调函数
4.解决注册的回到函数执行时出现异常,增加方法 registerError 用于处理异常情况
5.定义 assign 方法,用于通过 JS 触发 history.pushState 函数
6.定义 replace 方法,用于通过 JS 触发 history.replaceState 函数
7.监听 popstate 用于处理前进后退时调用对应的回调函数
8.全局阻止A链接的默认事件,获取A链接的href属性,并调用 history.pushState 方法
9.定义 load 方法,用于首次进入页面时 根据 location.pathname 调用对应的回调函数
//html

<body>
<div id="nav">
<a href="/page1">page1</a>
<a href="/page2">page2</a>
<a href="/page3">page3</a>
<a href="/page4">page4</a>
<a href="/page5">page5</a>
<button id="btn">page2</button>
</div>
<div id="container"> </div>
</body>

//js测试

let router = new HistoryRouter();
let container = document.getElementById('container'); //注册首页回调函数
router.registerIndex(() => container.innerHTML = '我是首页'); //注册其他视图回到函数
router.register('/page1', () => container.innerHTML = '我是page1');
router.register('/page2', () => container.innerHTML = '我是page2');
router.register('/page3', () => container.innerHTML = '我是page3');
router.register('/page4', () => {
throw new Error('抛出一个异常')
}); document.getElementById('btn').onclick = () => router.assign('/page2') //注册未找到对应path值时的回调
router.registerNotFound(() => container.innerHTML = '页面未找到');
//注册出现异常时的回调
router.registerError((e) => container.innerHTML = '页面异常,错误消息:<br>' + e.message);
//加载页面
router.load();

history路由的更多相关文章

  1. Router和History (路由控制)-backbone

    Router和History (路由控制) Backbone.Router担任了一部分Controller(控制器)的工作,它一般运行在单页应用中,能将特定的URL或锚点规则绑定到一个指定的方法(后文 ...

  2. 告别 hash 路由,迎接 history 路由

    博客地址:https://ainyi.com/69 三月来了,春天还会远吗.. 在这里,隆重宣布本博客告别 Vue 传统的 hash 路由,迎接好看而优雅的 history 路由~~ 映照官方说法 v ...

  3. 单页面应用的History路由模式express后端中间件配合

    这篇文章主要分享一下通过HTML5的history API的时候,使用NodeJS后端应该如何配置,来避免产生404的问题,这里是使用的express的框架,主要是通过connect-history- ...

  4. history路由模式下的nginx配置

    路由模式 众所周知,浏览器下的单页面应用的路由模式有下面两种: hash 模式和 history 模式.hash 模式通用性好,而且不依赖服务器的配置,省心省力,但是缺点是不够优雅.相比于 hash ...

  5. vue cli3项目发布在apache www/vue目录下并配置history路由

    注意:vue项目打包后默认是指向服务器的根路径(比如apache默认www目录是根路径,当然也可以修改),这种情况不需要做路径的配置,只需要做history配置,如果不是发布到根路径而是www/vue ...

  6. vue采用history路由的服务器部署问题

    发现部署问题 在部署的时候发现打开的页面是空白 之前部署原理 之前的页面都是作为静态文件形式打包上传到服务器上 http://www.xiedashuaige.cn/bolg2.0/#/home 就和 ...

  7. nginx 一个端口布署多个单页应用(history路由模式)。

    目前web开发 使用一般前后端分离技术,并且前端负责路由.为了美观,会采用前端会采用h5 history 模式的路由.但刷新页面时,前端真的会按照假路由去后端寻找文件.此时,后端必须返回index(i ...

  8. nginx history路由模式时,页面返回404重定向index.html

    1.路由默认是带#的,有时我们感觉不美观,就使其变为history模式,也就没有#字符 2.# 如果找不到当前页面(404),就返回index.html,重新分配路由 location ^~/prod ...

  9. hash和history路由的区别

    在了解路由模式前,我们先看下 什么是单页面应用,vue-router  的实现原理是怎样的,这样更容易理解路由. SPA与前端路由 SPA(单页面应用,全程为:Single-page Web appl ...

随机推荐

  1. Zeta(2) 有图版

    我很早就一直想写一篇文章,跟大家聊一聊: $$\frac{1}{1^2}+\frac{1}{2^2} +\frac{1}{3^2} +\frac{1}{4^2} +\frac{1}{5^2} +\cd ...

  2. layui-form下隐藏元素的验证问题

    1.情景: 设置为display:none的必填字段,在点击提交(form 包含 class="layui-form":button包含属性 lay-submit)的时候,依旧验证 ...

  3. MySQL学习(四)死锁及死锁检测

    文章图片来自参考资料 MySQL 的锁     根据加锁的范围,MySQL里面的锁大致可以分成全局锁.表级锁和行锁三类.我们需要明白锁的服务是为了数据统一,或者说是事务,数据隔离. 全局锁     全 ...

  4. angular项目实现mqtt的订阅与发布 ngx-mqtt

    angular项目实现mqtt的订阅与发布 如果要写一个exe可执行文件,可以使用angular编写,然后使用electron打包成一个exe文件. https://github.com/maxime ...

  5. HTML学习(10)图像

    HTML图像标签<img>,没有闭合标签 <img src="" alt="" width="" height=" ...

  6. 每天进步一点点------Allegro 铺铜详解

    铺铜在设计PCB板时很重要,为了加深理解,笔者写下这篇学习的过程. 首先要理解什么是正片和负片,结合网上的资料来理解一下: 正片实际就是能在底片上能看到的就是存在的 负片实际上就是在底片看到的就是不存 ...

  7. CentOS 7 下挂载NTFS盘及开机自动挂载

    一.工具 NTFS-3G 二.安装2种安装方式 2.1.yum安装 yum install NTFS* 2.2.编译安装 下载 解压 wget https://tuxera.com/opensourc ...

  8. RestTemplate-记录

    org.springframework.web.client.RestTemplate 1.从使用功能上看,是一种简化请求响应的工具类,从发送请求,到对返回的结果进行json解析.格式不对会有异常.

  9. Codeforces Round #624 (Div. 3) A. Add Odd or Subtract Even(水题)

    You are given two positive integers aa and bb . In one move, you can change aa in the following way: ...

  10. 【原】docker基础(一)

    1.架构 2.说明 Docker daemon( Docker守护进程):Docker daemon是一个运行在宿主机( DOCKER-HOST)的后台进程.可通过 Docker客户端与之通信. Cl ...