前端路由一般分为两种方式
- hash路由
- H5 History路由
简单介绍下这两个路由:
hash路由
- 标志:hash路由的标志是带有#
- 原理:通过监听url中的hash值变化来进行路由跳转。
- 优势:兼容性更好,在老版IE中都有运行
- 问题:url中一直存在#,页面不够美观
实现
- 新增Route类
- 构造函数中增加实例属性routers用于存储路由,currentUrl用于保存当前页面地址。
- 构造函数中添加对路由变化的监听
- 新增注册函数route
- 新增回退函数back
- 构造函数中新增history数组,用于保存历史hash
- 构造函数中新增currentIndex实例属性,用于追踪历史hash
class Router {
constructor() {
this.routes = {}; //键值对形式存储路由信息
this.currentUrl = ''; //当前Url
this.history = []; //hash历史
this.currentIndex =this.history.length - 1; //默认指向当前最新的hash
window.addEventListener('load', this.refresh, false);
window.addEventListener('hashchange', this.refresh, false);
this.refresh = this.refresh.bind(this);
this.back = this.back.bind(this);
}
route(path, calllback) {
// 注册路由
this.routes[path] = callback || function () {}
}
refresh() {
// 获取除去#的hash值
this.currentUrl = location.hash.slice(1);
this.history.push(this.currentUrl);
this.currentIndex++;
this.routes[this.currentUrl] && this.routes[this.currentUrl]();
}
back() {
// 如果当前指向历史最早的hash,不再回退
this.currentIndex >= 0? (this.currentIndex = 0) : (this.currentIndex -= 1);
this.currentUrl = this.history[this.currentIndex];
this.routes[this.currentUrl] && this.routes[this.currentUrl]();
}
}
H5 History路由
H5新增的History对象,里面有各种API,常用API包含以下3个:
window.history.back(); // 后退
window.history.forward(); // 前进
window.history.go(-3); // 后退三个页面
在浏览器点击前进后退就会调用以上API。想要实现路由,还有几个重要的API需要我们知道:
- history.pushState
用于在浏览历史中添加历史记录,但是并不触发跳转,此方法接受三个参数,依次为:
(1)state:一个与指定网址相关的状态对象。popstate事件触发时才会产生,如果不需要可以填null。
(2)title:新页面的标题,一般为null。
(3)url:新的网址,要求与当前页面处在同一个域。 - history.replaceState
方法参数与pushState方法一样,区别是它修改浏览历史中当前纪录,而非添加记录,同样不触发跳转。 - popstate事件
每当同一个文档的history对象出现变化时,就会触发popstate事件。仅仅调用pushState方法或replaceState方法并不会触发该事件。只有当用户点击浏览器倒退按钮和前进按钮,或使用js调用back、forward、go方法时才会触发。
实现
class Router {
constructor() {
this.routes = {};
// 构造函数中监听popstate
this.watchPopState();
this.init = this.init.bind(this);
this.go = this.go.bind(this);
this.back = this.back.bind(this);
}
route(path, calllback) {
// 注册路由
this.routes[path] = callback || function () {}
}
init(path){
history.replaceState({path: path}, null, path);
this.routes[path] && this.routes[path]();
}
go(path) {
history.pushState({path: path}, null, path);
this.routes[path] && this.routes[path]();
}
back() {
history.back();
}
watchPopState() {
window.addEventListener('popstate', e => {
const path = e.state && e.state.path;
this.routes[path] && this.routes[path]();
})
}
}
使用方式如下:
window.Router = new Routers();
Router.init(location.pathname);
Router.route('/', function() {
changeBgColor('yellow');
})
let link = document.querySelector('a');
link.addEventListener('click', e => {
e.preventDefault();
let href = e.target.getAttribute('href')
Router.go(href);
}, false);
网友评论