如何在Material Design菜单中添加用户输入的自定义菜单项
实现方案说明
核心问题答复
可以直接通过追加DOM元素的方式实现自定义菜单项添加,但需要遵循Material Design Component(MDC)的组件更新规则,否则新增的菜单项不会触发涟漪效果、键盘导航等原生MDC交互。
现有代码优化提示
你当前的HTML嵌套了两层mdc-menu mdc-menu-surface,属于冗余结构,建议删掉外层重复的那层,调整后结构如下(可选优化,不影响功能但减少冗余DOM):
<div id="demo-menu" class="mdc-menu-surface--anchor"> <button class="material-icons mdc-top-app-bar__navigation-icon mdc-icon-button" aria-label="Open navigation menu">edit</button> <div class="mdc-menu mdc-menu-surface"> <ul class="mdc-list" role="menu" aria-hidden="true" aria-orientation="vertical" tabindex="-1"> <li class="mdc-list-item" role="menuitem"> <span class="mdc-list-item__ripple"></span> <span class="mdc-list-item__text">A Menu Item</span> </li> </ul> </div> </div>
具体实现步骤
- 第一步:先初始化MDC Menu组件并保存实例,后续更新需要用到
// 初始化菜单实例 const menuEl = document.querySelector('.mdc-menu'); const menu = mdc.menu.MDCMenu.attachTo(menuEl); // 拿到菜单项列表容器 const menuList = menuEl.querySelector('.mdc-list');
- 第二步:获取用户输入内容,构造符合MDC规范的菜单项DOM,注意要转义用户输入避免XSS风险
// 假设userInput是用户输入的文本 function addMenuItem(userInput) { // 构造菜单项 const li = document.createElement('li'); li.className = 'mdc-list-item'; li.setAttribute('role', 'menuitem'); const ripple = document.createElement('span'); ripple.className = 'mdc-list-item__ripple'; const text = document.createElement('span'); text.className = 'mdc-list-item__text'; // 用textContent赋值自动转义特殊字符,避免XSS text.textContent = userInput; li.appendChild(ripple); li.appendChild(text); // 追加到列表 menuList.appendChild(li); // 关键:调用layout方法更新菜单内部状态,让新元素生效 menu.layout(); }
- 第三步:如果需要批量添加多个菜单项,可以全部追加完成后再调用一次
menu.layout()即可,无需每追加一个就调用一次,提升性能。
注意事项
- 不要直接把用户输入内容用
innerHTML插入DOM,避免恶意脚本注入,优先用textContent赋值文本 - 如果需要给新增菜单项绑定点击事件,可以在构造li元素的时候直接添加
addEventListener即可,MDC的交互逻辑不会影响自定义事件
内容的提问来源于stack exchange,提问作者meli v
相关产品推荐
相关产品推荐

