一,前言
上篇,介绍创建路由映射表,主要包含以下内容:
本篇,继续介绍两种路由模式的设计;
二,承上启下
1,前文回顾
2,本篇介绍
有了路由配置的映射关系之后,还需要实现根据不同路径跳转并显示对应的组件;本篇,主要介绍两种路由模式的设计及初始化操作;
三,路由跳转的实现
1,路由模式的处理
根据路由选项中所配置的不同路由模式,需要进行不同的处理;
路由模式共有三种,主要介绍 Hash 和 History 两种模式:
// index.js
import HashHistory from './history/hash';
import BrowserHistory from './history/history';
class VueRouter {
constructor(options) {
// 路由配置的扁平化处理
this.matcher = createMatcher(options.routes || []);
// 根据不同的路由模式,生成对应的处理实例
options.mode = options.mode || 'hash'; // 默认hash模式
switch (options.mode) {
case 'hash':
this.history = new HashHistory(this);
break;
case 'history':
this.history = new BrowserHistory(this);
break;
}
}
// 路由初始化方法,供 install 安装时调用
init(app) {}
}
VueRouter.install = install;
export default VueRouter;
复制代码
路由切换时,需要通过 matcher 进行规则匹配,所以在创建两种理由模式的类时,需要传入 this,即当前路由实例;
2,创建两种路由模式类:HashHistory 和 BrowserHistory
创建两种路由模式对应的类:HashHistory 和 BrowserHistory,他们均继承自路由的公共逻辑处理 History 类;
History 类:HashHistory 和 BrowserHistory 的父类,包含两种路由模式的公共逻辑处理:
// history/base.js
class History {
constructor(router) {
this.router = router; // 存储子类传入的 router 实例
}
}
export { History }
复制代码
HashHistory 类:继承自 History 类,对应 Hash 模式下方法的实现:
// history/hash.js
import { History } from "./base";
class HashHistory extends History{
constructor(router) {
super(router); // 调用父类构造方法,并将 router 实例传给父类
this.router = router; // 存储 router 实例,共内部使用
}
}
export default HashHistory
复制代码
BrowserHistory 类:继承自 History 类,对应 History 模式下方法的实现:
// ---------------------------- //
// history/hash.js
import { History } from "./base";
class BrowserHistory extends History{
constructor(router) {
super(router); // 调用父类构造方法,并将 router 实例传给父类
this.router = router; // 存储 router 实例,共内部使用
}
}
export default BrowserHistory
复制代码
3,Hash 模式的路径处理
Hash 模式下,路径后会默认携带'/'符号,HashHistory 初始化时进行处理;
import { History } from "./base";
function ensureSlash() {
// location.hash 存在兼容性问题,可根据完整 URL 判断是否包含'/'
if (window.location.hash) {
return;
}
window.location.hash = '/'; // 如果当前路径没有hash,默认为 /
}
class HashHistory extends History {
constructor(router) {
super(router);
this.router = router;
// Hash 模式下,对URL路径进行处理,确保包含'/'
ensureSlash();
}
}
export default HashHistory
复制代码
4,父类和子类的设计
无论是哪一种路由模式 HashHistory 或 BrowserHistory 都需要通过当前的路径进行路由匹配和跳转
路径获取:Hash 模式获取当前路径 hash 值,history 模式获取当前路径 path 值;
路由监听:Hash 模式监听 hashchange 事件,history 模式监听 popState 事件;
父类和子类的方法设计:
base.js:
transitionTo 根据路由进行匹配跳转;
hash.js:
getCurrentLocation:获取当前路径 hash 值;
setupListener:监听 hashchange 事件
history.js:
getCurrentLocation:获取当前路径 path 值;
setupListener:监听 popState 事件
5, 父类和子类方法的实现
父类 History:
// base.js
class History {
constructor(router) {
this.router = router;
}
// 根据路径进行路由匹配,并添加路径改变的监听器
transitionTo(location, onComplete) {
onComplete && onComplete();
}
}
export { History }
复制代码
Hash 模式的子类 HashHistory:
import { History } from "./base";
class HashHistory extends History{
constructor(router){
super(router);
this.router = router;
ensureSlash();
}
getCurrentLocation(){
// 获取路径的 hash 值
return getHash();
}
setupListener(){
// 当 hash 值变化时,获取新的 hash 值,并进行匹配跳转
window.addEventListener('hashchange',()=>{
this.transitionTo(getHash());
})
}
}
export default BrowserHistory
复制代码
History 模式的子类 HashHistory:
class BrowserHistory extends History{
setupListener(){
// 当路径变化时,拿到新的 hash 值,并进行匹配跳转
window.addEventListener('popState',()=>{
this.transitionTo(getHash());
})
}
}
export default BrowserHistory
复制代码
6,路由初始化 init 方法
// index.js
class VueRouter {
constructor(options) {
this.matcher = createMatcher(options.routes || []);
options.mode = options.mode || 'hash';
switch (options.mode) {
case 'hash':
this.history = new HashHistory(this);
break;
case 'history':
this.history = new BrowserHistory(this);
break;
}
}
// 监听 hash 值变化,跳转到对应的路径中
init(app) {
// 当前的history实例:可能是HashHistory,也可能是BrowserHistory;
const history = this.history;
// 设置监听器:内部调用的是不同子类中的实现
const setUpListener = () => {
history.setupListener();
}
// 初始化时,获取当前hash值进行跳转, 并设置监听器
history.transitionTo(
history.getCurrentLocation(),
setUpListener
)
}
}
VueRouter.install = install;
export default VueRouter;
复制代码
四,结尾
本篇,介绍了两种路由模式的设计及初始化操作,主要涉及以下几个点:
创建两种路由模式类;
父类和子类继承方法的设计;
路由初始化 init 处理逻辑;
下一篇,路由匹配的实现;
评论