介绍 
将一个无序列表转化为一个带图标的可折叠/展开的菜单。下面是三种实现方法。
使用 Web Components 
- 首先使用 customElements.define()方法注册一个元素。
js
customElements.define('expanding-list', ExpandingList, { extends: 'ul' });第三个参数是一个包含 extends 属性的配置对象,指定了所创建的元素继承自哪个内置元素,可以继承任何内置元素。
- 然后,定义这个元素的实现类 ExpandingList,并继承HTMLUListElement。
js
class ExpandingList extends HTMLUListElement {
  constructor() {
    self = super();
    self.querySelectorAll('li').forEach(li => {
      if (li.querySelector('ul')) {
        li.setAttribute('class', 'closed');
        const { firstChild } = li;
        // 使用 span 替换 li 节点文本,并绑定事件
        const newSpan = document.createElement('span');
        newSpan.textContent = firstChild.textContent;
        newSpan.onclick = self.showul;
        firstChild.replaceWith(newSpan);
      }
    });
  }
  // 折叠/展开菜单
  showul(e) {
    const nextul = e.target.nextElementSibling;
    if (nextul.style.display == 'block') {
      nextul.style.display = 'none';
      nextul.parentNode.setAttribute('class', 'closed');
    } else {
      nextul.style.display = 'block';
      nextul.parentNode.setAttribute('class', 'open');
    }
  };
}- 在页面上使用 <ul>标签,通过is属性指定这个自定义内置元素的名称。
html
<ul is="expanding-list">
</ul>is 全局属性是一种使用 Web 组件的方法,是将自定义元素(实现了 Web 组件逻辑)插入页面的另一种方式。
- 不是使用自定义元素的名称作为 HTML 标记,而是将名称传递给内置 HTML 元素。
- 如果 Web 组件没有在页面上注册,该组件仍可以退回到标准 HTML 元素行为。
使用 details 和 summary 标签配合 ::marker 伪元素 
- <details>元素可创建一个部件,仅在被切换成展开状态时,它才会显示内含的信息。
- <summary>元素可为- <details>部件提供显示的标题信息。默认标题信息左边会有一个小三角形图标。
- ::markerCSS 伪元素可为设置了- display: list-item的元素或伪元素上定义样式,例如- <li>和- <summary>,它们通常含有一个项目符号或者数字。但是,目前只能使用某些 CSS 属性:- 所有字体属性
- white-space
- color
- text-combine-upright, unicode-bidi, direction
- content
- 所有 animation 和 transition 属性
 
使用 input checkbox 和 label 标签 
使用单选框以及复选框自带的一些特性,然后配合 CSS 一些特殊的选择器,可以在不使用任何 JavaScript 代码情况下实现元素的显示隐藏、多级下拉列表、选项卡切换效果等。目前兼容性最好。
浏览器支持 
目前,Safari 浏览器对前两种方法都不支持。