```
feat(router): 引入路由系统并重构页面结构 - 为项目引入基于 hash 的前端路由系统,支持多页面切换与动态加载 - 将原有单一 bundle 拆分为多个入口打包(index.js 和 timestamp.js) - 修改 Rollup 配置以支持多输出文件及插件共享 - 更新 HTML 结构以适配路由容器和页面占位元素 - 调整 CSS 样式,移除旧的页面切换动画,交由路由控制 - 优化 domUtils 工具函数,并迁移部分样式处理逻辑 - 在 timestamp.js 中封装初始化函数以便路由调用 - todolist 页面模板新增,用于后续功能开发 ```
This commit is contained in:
@@ -11,11 +11,11 @@ export function switchPage(pageName) {
|
||||
const currentPage = document.querySelector('.page.active');
|
||||
if (currentPage) {
|
||||
currentPage.classList.remove('active');
|
||||
|
||||
|
||||
// 添加离开动画
|
||||
currentPage.style.opacity = '0';
|
||||
currentPage.style.transform = 'translateX(20px)';
|
||||
|
||||
|
||||
// 等待动画完成后真正隐藏
|
||||
setTimeout(() => {
|
||||
if (!currentPage.classList.contains('active')) {
|
||||
@@ -33,14 +33,14 @@ export function switchPage(pageName) {
|
||||
const targetPage = document.getElementById(`page-${pageName}`);
|
||||
if (targetPage) {
|
||||
targetPage.style.display = 'block';
|
||||
|
||||
|
||||
// 触发重排以确保display变化生效
|
||||
targetPage.offsetHeight;
|
||||
|
||||
|
||||
// 添加进入动画
|
||||
targetPage.style.opacity = '0';
|
||||
targetPage.style.transform = 'translateX(-20px)';
|
||||
|
||||
|
||||
setTimeout(() => {
|
||||
targetPage.classList.add('active');
|
||||
targetPage.style.opacity = '1';
|
||||
@@ -49,7 +49,8 @@ export function switchPage(pageName) {
|
||||
}
|
||||
|
||||
// 激活对应的导航按钮
|
||||
const navButton = document.getElementById(`nav-${pageName}-btn`) || document.getElementById(`nav-${pageName}`);
|
||||
const navButton =
|
||||
document.getElementById(`nav-${pageName}-btn`) || document.getElementById(`nav-${pageName}`);
|
||||
if (navButton) {
|
||||
navButton.classList.add('active');
|
||||
}
|
||||
@@ -75,4 +76,46 @@ export function addEventListenerById(id, event, handler) {
|
||||
if (element) {
|
||||
element.addEventListener(event, handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断元素是否包含指定类名
|
||||
* @param {*} elem
|
||||
* @param {*} cls
|
||||
* @returns
|
||||
*/
|
||||
export function hasClass(elem, cls) {
|
||||
cls = cls || '';
|
||||
// 检测类名是否为''
|
||||
if (cls.replace(/\s/g, '').length === 0) return false;
|
||||
// 检测elem类名是否包含cls指定类名
|
||||
return new RegExp(' ' + cls + ' ').test(' ' + elem.className + ' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* 为元素添加类名
|
||||
* @param {*} elem
|
||||
* @param {*} cls
|
||||
*/
|
||||
export function addClass(elem, cls) {
|
||||
if (!hasClass(elem, cls)) {
|
||||
elem.className = elem.className === '' ? cls : elem.className + ' ' + cls;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 为元素删除类名
|
||||
* @param {*} elem
|
||||
* @param {*} cls
|
||||
*/
|
||||
export function removeClass(elem, cls) {
|
||||
if (hasClass(elem, cls)) {
|
||||
let newClass = ' ' + elem.className.replace(/[\t\r\n]/g, '') + ' ';
|
||||
// 删除指定类名
|
||||
while (newClass.indexOf(' ' + cls + ' ') >= 0) {
|
||||
newClass = newClass.replace(' ' + cls + ' ', ' ');
|
||||
}
|
||||
// 重新赋值
|
||||
elem.className = newClass.replace(/^\s+|\s+$/);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
/**
|
||||
* 获取路由的路径和详情参数
|
||||
* @returns
|
||||
* 获取路由的路径和详细参数
|
||||
* @returns
|
||||
*/
|
||||
export function getParamsUrl() {
|
||||
let hasDetail = location.hash.split('?');
|
||||
let hasName = hasDetail[0].split('#')[1];
|
||||
let params = hasDetail[1] ? hasDetail[1].split('&') : [];
|
||||
// 获取路由
|
||||
const hasDetail = location.hash.split('?');
|
||||
// 获取路由名称
|
||||
const hasName = hasDetail[0].split('#')[1];
|
||||
// 获取请求参数
|
||||
const params = hasDetail[1] ? hasDetail[1].split('&') : [];
|
||||
// 解析请求参数
|
||||
let query = {};
|
||||
|
||||
for (let i = 0; i < params.length; i++) {
|
||||
let param = params[i].split('=');
|
||||
query[param[0]] = param[1];
|
||||
@@ -20,40 +23,26 @@ export function getParamsUrl() {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 闭包返回函数
|
||||
* @param {*} name
|
||||
* @returns
|
||||
*/
|
||||
export function closure(name) {
|
||||
function fun(currentHash) {
|
||||
window.name&&window[name](currentHash)
|
||||
}
|
||||
return fun;
|
||||
return (currentHash) => {
|
||||
window.name && window[name](currentHash);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机key
|
||||
* @returns
|
||||
*/
|
||||
export function genKey() {
|
||||
let temp = 'xxxxxxxx';
|
||||
return temp.replace(/[xy]/g, function (c) {
|
||||
let r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
const KEY_TEMPLATE = 'xxxxxxxx';
|
||||
return KEY_TEMPLATE.replace(/[xy]/g, (c) => {
|
||||
const r = (Math.random() * 16) | 0;
|
||||
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
|
||||
export function hasClass(elem, cls) {
|
||||
cls = cls || '';
|
||||
if (cls.replace(/\s/g, '').length === 0)
|
||||
return false;
|
||||
return new RegExp(' ' + cls + ' ').test(' ' + elem.className + ' ');
|
||||
}
|
||||
|
||||
export function addClass(elem, cls) {
|
||||
if (!hasClass(elem, cls)) {
|
||||
elem.className = elem.className === '' ? cls : elem.className + ' ' + cls;
|
||||
}
|
||||
}
|
||||
|
||||
export function removeClass(elem, cls) {
|
||||
if (hasClass(elem, cls)) {
|
||||
let newClass = ' ' + elem.className.replace(/[\t\r\n]/g, '') + ' ';
|
||||
while (newClass.indexOf(' ' + cls + ' ') >= 0) {
|
||||
newClass = newClass.replace(' ' + cls + ' ', ' ');
|
||||
}
|
||||
elem.className = newClass.replace(/^\s+|\s+$/)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user