fix(navigation): 改用原生DOM操作,彻底解决h函数问题
- 放弃Vue h函数,直接document.createElement创建导航栏 - mounted生命周期中渲染侧边栏和移动端底部导航 - 原生JS绑定点击事件,确保功能正常 - 避免Vue3 prod版本中render函数的参数问题
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
// Vue 3 导航组件 - 最终版(增强调试和样式)
|
// 最简导航组件 - 原生DOM操作(无h函数)
|
||||||
(function() {
|
(function() {
|
||||||
console.log('[Nav] 脚本加载');
|
console.log('[Nav] 脚本加载');
|
||||||
|
|
||||||
@@ -45,52 +45,65 @@
|
|||||||
console.log('[Nav] 样式已注入');
|
console.log('[Nav] 样式已注入');
|
||||||
}
|
}
|
||||||
|
|
||||||
function getHFromApp(app) {
|
|
||||||
try {
|
|
||||||
if (app._context && app._context.h) return app._context.h;
|
|
||||||
if (app._instance && app._instance.proxy && app._instance.proxy._cf) return app._instance.proxy._cf;
|
|
||||||
} catch (e) { console.warn('[Nav] 获取 h 失败', e); }
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const installNavigation = (app) => {
|
const installNavigation = (app) => {
|
||||||
console.log('[Nav] installNavigation called');
|
console.log('[Nav] installNavigation called');
|
||||||
injectStyles();
|
injectStyles();
|
||||||
const h = getHFromApp(app) || (window.Vue && Vue.h) || function(tag, data, children) {
|
|
||||||
const el = document.createElement(tag);
|
|
||||||
if (data && data.class) el.className = data.class;
|
|
||||||
if (children) {
|
|
||||||
if (Array.isArray(children)) children.forEach(c => { if (typeof c === 'string') el.appendChild(document.createTextNode(c)); else if (c && c.nodeType) el.appendChild(c); });
|
|
||||||
else if (typeof children === 'string') el.textContent = children;
|
|
||||||
}
|
|
||||||
if (data && data.on) Object.keys(data.on).forEach(ev => el.addEventListener(ev, data.on[ev]));
|
|
||||||
return el;
|
|
||||||
};
|
|
||||||
console.log('[Nav] 使用 h 函数:', typeof h);
|
|
||||||
|
|
||||||
|
// 定义组件选项
|
||||||
const component = {
|
const component = {
|
||||||
name: 'NavigationComponent',
|
name: 'NavigationComponent',
|
||||||
props: { currentPage: { type: String, required: true }, isAdmin: { type: Boolean, default: false } },
|
props: { currentPage: { type: String, required: true }, isAdmin: { type: Boolean, default: false } },
|
||||||
mounted() { console.log('[NavigationComponent] 已挂载,isAdmin:', this.isAdmin); },
|
mounted() {
|
||||||
render(){
|
console.log('[NavigationComponent] 已挂载', this.currentPage, this.isAdmin);
|
||||||
const createElement = arguments[0] || h;
|
|
||||||
const emit = this.$emit || function() {};
|
|
||||||
|
|
||||||
const navigate = (page) => {
|
// 在组件挂载后立即渲染导航栏到DOM
|
||||||
console.log('[NavigationComponent] 点击导航到:', page);
|
setTimeout(() => {
|
||||||
if (typeof emit === 'function') {
|
const container = this.$el; // 组件根元素
|
||||||
emit('navigate', page);
|
container.innerHTML = '';
|
||||||
} else if (this.$emit) {
|
|
||||||
this.$emit('navigate', page);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const sidebarItems = [
|
// 渲染侧边栏
|
||||||
|
const sidebar = document.createElement('aside');
|
||||||
|
sidebar.className = 'sidebar';
|
||||||
|
|
||||||
|
const header = document.createElement('div');
|
||||||
|
header.className = 'sidebar-header';
|
||||||
|
const headerTitle = document.createElement('h3');
|
||||||
|
headerTitle.textContent = '宇之然平台';
|
||||||
|
header.appendChild(headerTitle);
|
||||||
|
|
||||||
|
const nav = document.createElement('nav');
|
||||||
|
nav.className = 'sidebar-nav';
|
||||||
|
|
||||||
|
const items = [
|
||||||
{ icon: '📊', label: '系统概览', page: '/' },
|
{ icon: '📊', label: '系统概览', page: '/' },
|
||||||
{ icon: '📋', label: '选题管理', page: 'topics.html' },
|
{ icon: '📋', label: '选题管理', page: 'topics.html' },
|
||||||
{ icon: '📄', label: '系统日志', page: 'logs.html' },
|
{ icon: '📄', label: '系统日志', page: 'logs.html' },
|
||||||
...(this.isAdmin ? [{ icon: '👥', label: '用户管理', page: 'users.html' }, { icon: '⚙️', label: '系统管理', page: 'admin.html' }] : [])
|
...(this.isAdmin ? [{ icon: '👥', label: '用户管理', page: 'users.html' }, { icon: '⚙️', label: '系统管理', page: 'admin.html' }] : [])
|
||||||
];
|
];
|
||||||
|
|
||||||
|
items.forEach(item => {
|
||||||
|
const btn = document.createElement('button');
|
||||||
|
btn.className = this.currentPage === (item.page === '/' ? 'dashboard' : item.page.replace('.html',''))
|
||||||
|
? 'sidebar-btn active' : 'sidebar-btn';
|
||||||
|
btn.textContent = item.icon + ' ' + item.label;
|
||||||
|
|
||||||
|
btn.addEventListener('click', () => {
|
||||||
|
console.log('[NavigationComponent] 点击导航到:', item.page);
|
||||||
|
this.$emit('navigate', item.page);
|
||||||
|
});
|
||||||
|
|
||||||
|
nav.appendChild(btn);
|
||||||
|
});
|
||||||
|
|
||||||
|
sidebar.appendChild(header);
|
||||||
|
sidebar.appendChild(nav);
|
||||||
|
container.appendChild(sidebar);
|
||||||
|
|
||||||
|
// 渲染移动端底部导航
|
||||||
|
if (window.innerWidth <= 768) {
|
||||||
|
const mobileNav = document.createElement('nav');
|
||||||
|
mobileNav.className = 'mobile-nav';
|
||||||
|
|
||||||
const mobileItems = [
|
const mobileItems = [
|
||||||
{ icon: '📊', label: '', page: '/' },
|
{ icon: '📊', label: '', page: '/' },
|
||||||
{ icon: '📋', label: '选题', page: 'topics.html' },
|
{ icon: '📋', label: '选题', page: 'topics.html' },
|
||||||
@@ -98,30 +111,25 @@
|
|||||||
...(this.isAdmin ? [{ icon: '👥', label: '用户', page: 'users.html' }, { icon: '⚙️', label: '系统', page: 'admin.html' }] : [])
|
...(this.isAdmin ? [{ icon: '👥', label: '用户', page: 'users.html' }, { icon: '⚙️', label: '系统', page: 'admin.html' }] : [])
|
||||||
];
|
];
|
||||||
|
|
||||||
console.log('[NavigationComponent] 渲染侧边栏项目:', sidebarItems.length, '移动端项目:', mobileItems.length);
|
mobileItems.forEach(item => {
|
||||||
|
const btn = document.createElement('button');
|
||||||
|
btn.className = this.currentPage === (item.page === '/' ? 'dashboard' : item.page.replace('.html',''))
|
||||||
|
? 'mobile-nav-btn active' : 'mobile-nav-btn';
|
||||||
|
|
||||||
return createElement('div', { class: 'navigation-wrapper' }, [
|
|
||||||
createElement('aside', { class: 'sidebar' }, [
|
|
||||||
createElement('div', { class: 'sidebar-header' }, [createElement('h3', '宇之然平台')]),
|
|
||||||
createElement('nav', { class: 'sidebar-nav' }, sidebarItems.map(item => {
|
|
||||||
const isActive = this.currentPage === (item.page === '/' ? 'dashboard' : item.page.replace('.html',''));
|
|
||||||
return createElement('button', {
|
|
||||||
key: item.page,
|
|
||||||
class: isActive ? 'sidebar-btn active' : 'sidebar-btn',
|
|
||||||
on: { click: (e) => { e.preventDefault(); navigate(item.page); } }
|
|
||||||
}, item.icon + ' ' + item.label);
|
|
||||||
}))
|
|
||||||
]),
|
|
||||||
createElement('nav', { class: 'mobile-nav' }, mobileItems.map(item => {
|
|
||||||
const isActive = this.currentPage === (item.page === '/' ? 'dashboard' : item.page.replace('.html',''));
|
|
||||||
const content = item.label ? (item.icon + ' ' + item.label) : item.icon;
|
const content = item.label ? (item.icon + ' ' + item.label) : item.icon;
|
||||||
return createElement('button', {
|
btn.textContent = content;
|
||||||
key: item.page,
|
|
||||||
class: isActive ? 'mobile-nav-btn active' : 'mobile-nav-btn',
|
btn.addEventListener('click', () => {
|
||||||
on: { click: (e) => { e.preventDefault(); navigate(item.page); } }
|
console.log('[NavigationComponent] 点击导航到:', item.page);
|
||||||
}, content);
|
this.$emit('navigate', item.page);
|
||||||
}))
|
});
|
||||||
]);
|
|
||||||
|
mobileNav.appendChild(btn);
|
||||||
|
});
|
||||||
|
|
||||||
|
container.appendChild(mobileNav);
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user