如何结合HTML元素高效运用对象编写可维护前端代码
人才管理系统下拉菜单OOP封装问题反馈
正在开发员工人才管理系统网站,开发下拉菜单模块时虽已采用面向对象(OOP)思路实现功能,但存在代码结构混乱、可维护性差的问题。目前仅掌握OOP基础概念,不清楚如何在实际项目中清晰、简洁地完成HTML元素与对象的结合封装,落地过程中遇到三类核心问题:
- 对象实例化与事件绑定流程冗余:通过for循环为人才门户中每个代表候选人的可切换菜单创建对象实例后,需要二次遍历实例列表,为各菜单绑定对应对象方法作为点击事件,实现方式不直观、运行效率偏低。
- 类内部条件判断过多:考虑到后续需要复用该对象实现其他菜单,而不同菜单的特性存在差异(例如此次实现的菜单点击后有淡入动画,但并非所有可切换菜单都需要该特性),在类中写了大量if判断处理可选配置,导致代码可读性、可维护性大幅下降。
- 事件绑定逻辑的封装边界不清晰:不认可当前额外遍历元素绑定事件的实现方式,曾考虑将事件绑定逻辑全部封装到对象内部,但不确定该做法是否属于不良实践。
后续计划在表单、按钮、可切换菜单、导航栏等各类组件中使用OOP实现,核心诉求是掌握清晰简洁的HTML元素转对象封装方法。此前学习过设计模式相关内容,认为相关概念偏进阶,适合在扎实掌握对象基础用法后再深入学习;目前比较认可建造者(Builder)模式,正在单独分支上尝试基于该模式优化当前场景的实现,以下为当前的ToggleMenu类定义与初始化实现代码,寻求相关实践思路、优化建议与学习方向。
ToggleMenu 类实现代码
class ToggleMenu { constructor(wrapper, menu, openIcon, closeIcon, title, hiddenMenu) { this.wrapper = wrapper this.menu = menu this.openIcon = openIcon this.closeIcon = closeIcon this.title = title this.hiddenMenu = hiddenMenu this.toggled = false } props() { console.log(this.menu) console.log(this.openIcon) console.log(this.closeIcon) console.log(this.title) console.log(this.hiddenMenu) console.log(this.toggled) } openHiddenMenu(config) { if (config == undefined){ config = {} } if (config.menuBackGroundColor !== undefined){ this.menu.style.backgroundColor = config.menuBackGroundColor } if (config.titleColor !== undefined){ this.title.style.color = config.titleColor } if (config.hiddenMenuDisplay !== undefined){ this.hiddenMenu.style.display = config.hiddenMenuDisplay } if (config.hiddenMenuAnimation !== undefined){ this.hiddenMenu.style.animationName = config.hiddenMenuAnimation } if(config.menuAnimation !== undefined){ this.menu.style.animationName = config.menuAnimation } this.openIcon.style.display = 'none' this.closeIcon.style.display = 'block' this.toggled = true } closeHiddenMenu(config){ if (config == undefined){ config = {} } if (config.menuAnimation !== undefined && this.toggled == true){ this.menu.style.animationName = config.menuAnimation } this.menu.style.backgroundColor = '' this.openIcon.style.display = '' this.closeIcon.style.display = '' this.title.style.color = '' this.hiddenMenu.style.display = '' this.toggled = false } }
菜单初始化逻辑代码
const initCandidateMenus = () => { let candidateToggleMenus = document.getElementsByClassName('candidate-toggle-menu') let candidateToggleWrappers = document.getElementsByClassName('candidate-toggle-menu-wrapper') let hiddenMenus = document.getElementsByClassName('hidden-candidate-menu') let toggleMenus = [] // 收集所有下拉菜单实例 for (x = 0; x < candidateToggleMenus.length; x++){ let toggleMenu = new ToggleMenu( candidateToggleWrappers[x], candidateToggleMenus[x], candidateToggleMenus[x].getElementsByClassName('candidate-open-icon')[0], candidateToggleMenus[x].getElementsByClassName('candidate-close-icon')[0], candidateToggleMenus[x].getElementsByClassName('candidate-name')[0], hiddenMenus[x], ) toggleMenus.push(toggleMenu) } // 遍历实例绑定交互事件 for (x = 0; x < toggleMenus.length; x++){ let currentMenu = toggleMenus[x] currentMenu.openIcon.addEventListener('click', () => { // 关闭其他所有已打开的下拉菜单 for (y = 0; y < toggleMenus.length; y++){ toggleMenus[y].closeHiddenMenu() } // 打开当前选中菜单 currentMenu.openHiddenMenu({ menuBackGroundColor: 'var(--main-clr)', titleColor: 'var(--white)', menuAnimation: 'fade-title-color', hiddenMenuDisplay: 'flex', hiddenMenuAnimation: 'open-hidden-menu' }) }) currentMenu.closeIcon.addEventListener('click', () => { // 关闭当前菜单 currentMenu.closeHiddenMenu() }) } }
内容的提问来源于stack exchange,提问作者Jacexecaj
相关产品推荐
相关产品推荐

