This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
import {
|
||||
RouteUtils,
|
||||
addClass,
|
||||
removeClass,
|
||||
hasClass,
|
||||
getParamsUrl,
|
||||
closure,
|
||||
genKey,
|
||||
} from '../utils/routeUtils.js';
|
||||
class Router {
|
||||
constructor() {
|
||||
// 路由表
|
||||
this.routes = {};
|
||||
// 路由跳转前执行
|
||||
this.beforeFun = null;
|
||||
// 路由跳转后执行
|
||||
this.afterFun = null;
|
||||
// 路由挂载点
|
||||
this.routerViewId = 'router-view';
|
||||
// 路由重定向hash
|
||||
this.redirectRoute = null;
|
||||
// 多级页面缓存
|
||||
this.stackPages = true;
|
||||
// 路由遍历
|
||||
this.routerMap = [];
|
||||
// 路由状态
|
||||
this.historyFlag = '';
|
||||
// 路由历史
|
||||
this.history = [];
|
||||
// 动画名称
|
||||
this.animationName = 'fade';
|
||||
}
|
||||
|
||||
init(config) {
|
||||
this.routerMap = config ? config.routers : this.routerMap;
|
||||
this.routerViewId = config ? config.routerViewId : this.routerViewId;
|
||||
this.stackPages = config ? config.stackPages : this.stackPages;
|
||||
|
||||
if (!this.routerMap.length) {
|
||||
let selector = this.routerViewId + '.page';
|
||||
let pages = document.querySelectorAll(selector);
|
||||
for (let i = 0; i < pages.length; i++) {
|
||||
let page = pages[i];
|
||||
let hash = page.getAttribute('hash');
|
||||
let name = hash.substring(1);
|
||||
this.routerMap.push({
|
||||
name: name,
|
||||
path: hash,
|
||||
callback: closure(name),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
window.linkTo = (path) => {
|
||||
console.log('path', path);
|
||||
if (path.indexOf('?') !== -1) {
|
||||
window.location.hash = path + '&key=' + genKey();
|
||||
} else {
|
||||
window.location.hash = path + '?key=' + genKey();
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener(
|
||||
'load',
|
||||
function (event) {
|
||||
this.historyChange(event);
|
||||
},
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 路由历史纪录变化
|
||||
* @param {*} event
|
||||
*/
|
||||
historyChange(event) {
|
||||
const currentHash = getParamsUrl();
|
||||
const nameString = 'router-' + this.routerViewId + '-history';
|
||||
this.history = window.sessionStorage[nameString]
|
||||
? JSON.parse(window.sessionStorage[nameString])
|
||||
: [];
|
||||
|
||||
let back = false,
|
||||
refresh = false,
|
||||
forward = false,
|
||||
index = 0,
|
||||
len = this.history.length;
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
let h = this.history[i];
|
||||
if (h.hash === currentHash.path && h.key === currentHash.query.key) {
|
||||
index = i;
|
||||
if (i === len - 1) {
|
||||
refresh = true;
|
||||
} else {
|
||||
back = true;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
forward = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (back) {
|
||||
this.historyFlag = 'back';
|
||||
this.history.length = index + 1;
|
||||
} else if (refresh) {
|
||||
this.historyFlag = 'refresh';
|
||||
} else {
|
||||
this.historyFlag = 'forward';
|
||||
this.history.push({
|
||||
key: currentHash.query.key,
|
||||
hash: currentHash.path,
|
||||
query: currentHash.query,
|
||||
});
|
||||
}
|
||||
|
||||
console.log('historyFlag', this.historyFlag);
|
||||
|
||||
if (!this.stackPages) {
|
||||
this.historyFlag = 'forward';
|
||||
}
|
||||
window.sessionStorage[nameString] = JSON.stringify(this.history);
|
||||
this.urlChange();
|
||||
}
|
||||
|
||||
changeView(currentHash) {
|
||||
const pages = document.querySelectorAll('.page');
|
||||
const previousPage = document.querySelector('.' + this.routerViewId + ' .page.active');
|
||||
let currentPage = null;
|
||||
let currentHash = null;
|
||||
|
||||
for (let i = 0; i < pages.length; i++) {
|
||||
let page = pages[i];
|
||||
let hash = page.getAttribute('hash');
|
||||
page.setAttribute('class', 'page');
|
||||
if (hash === currentHash.path) {
|
||||
currentHash = hash;
|
||||
currentPage = page;
|
||||
}
|
||||
}
|
||||
|
||||
const enterName = 'enter-' + this.animationName;
|
||||
const leaveName = 'leave-' + this.animationName;
|
||||
|
||||
if (this.historyFlag === 'back') {
|
||||
addClass(currentPage, 'current');
|
||||
if (previousPage) {
|
||||
addClass(previousPage, leaveName);
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
if (previousPage) {
|
||||
removeClass(previousPage, leaveName);
|
||||
}
|
||||
}, 300);
|
||||
} else if (this.historyFlag === 'forward' || this.historyFlag === 'refresh') {
|
||||
if (previousPage) {
|
||||
addClass(previousPage, leaveName);
|
||||
}
|
||||
addClass(currentPage, enterName);
|
||||
setTimeout(() => {
|
||||
if (previousPage) {
|
||||
removeClass(previousPage, leaveName);
|
||||
}
|
||||
addClass(currentPage, enterName);
|
||||
removeClass(currentPage, 'current');
|
||||
}, 300);
|
||||
currentPage.scrollTop = 0;
|
||||
this.routes[currentHash].callback ? this.routes[currentHash].callback() : null;
|
||||
}
|
||||
|
||||
this.afterFun ? this.afterFun(currentHash) : null;
|
||||
}
|
||||
|
||||
urlChange() {
|
||||
const currentHash = getParamsUrl();
|
||||
if (this.routes[currentHash.path]) {
|
||||
if (this.beforeFun) {
|
||||
this.beforeFun({
|
||||
to: {
|
||||
path: currentHash.path,
|
||||
query: currentHash.query,
|
||||
},
|
||||
next: () => {
|
||||
this.changeView(currentHash);
|
||||
},
|
||||
});
|
||||
} else {
|
||||
this.changeView(currentHash);
|
||||
}
|
||||
} else {
|
||||
location.hash = this.redirectRoute;
|
||||
}
|
||||
}
|
||||
|
||||
map() {
|
||||
for (let i = 0; i < this.routerMap.length; i++) {
|
||||
let route = this.routerMap[i];
|
||||
if (route.name === 'redirect') {
|
||||
this.redirectRoute = route.path;
|
||||
} else {
|
||||
this.redirectRoute = this.routerMap[0].path;
|
||||
}
|
||||
|
||||
let newPath = route.path;
|
||||
let path = newPath.repalce(/\s+/g, '');
|
||||
this.routes[path] = {
|
||||
callback: route.callback,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
beforeEach(callback) {
|
||||
if (Object.prototype.toString.call(callback) === '[object Function]') {
|
||||
this.beforeFun = callback;
|
||||
} else {
|
||||
console.trace('beforeEach callback must be a function');
|
||||
}
|
||||
}
|
||||
|
||||
afterEach(callback) {
|
||||
if (Object.prototype.toString.call(callback) === '[object Function]') {
|
||||
this.afterFun = callback;
|
||||
} else {
|
||||
console.trace('afterEach callback must be a function');
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user