js一般方法改写成面向对象方法的无限级折叠菜单示例代码

yizhihongxing

针对“js一般方法改写成面向对象方法的无限级折叠菜单示例代码”的完整攻略,我将分为以下几个部分进行介绍:

  1. 理解折叠菜单的基本原理
  2. 将一般方法改写成面向对象方法
  3. 根据面向对象方法实现无限级折叠菜单
  4. 示例说明

1. 理解折叠菜单的基本原理

折叠菜单是一种常见的交互式Web控件,它可以让用户在点击相应的菜单项时展开或收起相应的内容。实现折叠菜单的核心在于控制菜单项的打开或关闭状态,这通常可以通过添加或删除CSS类实现。同时,菜单项之间往往具有一定的层次关系,需要考虑如何处理多级嵌套的情况。

2. 将一般方法改写成面向对象方法

在面向对象编程中,我们通常将某个组件或功能抽象成一个类,类中包含相应的属性和方法。对于折叠菜单来说,我们可以把每一个菜单项抽象成一个对象,每个对象包含一些基本属性如ID、名称、状态等,以及一些方法如展开、收起、添加子项等。通过这种方式,我们可以更加方便地处理多级嵌套的菜单项。

3. 根据面向对象方法实现无限级折叠菜单

具体实现过程中,我们可以定义一个Menu类,代表整个菜单,包含一些基本属性如容器、根节点等,以及一些方法如初始化、添加子项、展开、收起等。对于每一个具体的菜单项,我们可以定义一个MenuItem类,包含一些基本属性如ID、名称、状态等,以及一些方法如展开、收起、添加子项等。在添加子项时,我们可以通过递归的方式处理多级嵌套的情况。

4. 示例说明

此处给出两个示例说明:

示例1

假设我们要实现一个两级嵌套的折叠菜单,包含三个顶级菜单项和每个顶级菜单项下面的两个子菜单项,在一般方法中,我们可以定义如下的菜单结构:

<div class="menu">
  <ul>
    <li><a href="#">菜单1</a>
      <ul>
        <li><a href="#">子菜单1-1</a></li>
        <li><a href="#">子菜单1-2</a></li>
      </ul>
    </li>
    <li><a href="#">菜单2</a>
      <ul>
        <li><a href="#">子菜单2-1</a></li>
        <li><a href="#">子菜单2-2</a></li>
      </ul>
    </li>
    <li><a href="#">菜单3</a>
      <ul>
        <li><a href="#">子菜单3-1</a></li>
        <li><a href="#">子菜单3-2</a></li>
      </ul>
    </li>
  </ul>
</div>

在改写成面向对象方法时,我们可以定义如下的Menu和MenuItem类:

class MenuItem {
  constructor(id, name) {
    this.id = id;
    this.name = name;
    this.state = false;
    this.children = [];
  }
  addChildren(child) {
    this.children.push(child);
  }
  open() {
    this.state = true;
  }
  close() {
    this.state = false;
  }
}

class Menu {
  constructor(container) {
    this.container = container;
    this.root = [];
  }
  addMenuItem(item) {
    this.root.push(item);
  }
  render() {
    let menuList = document.createElement('ul');
    for (let item of this.root) {
      let menuItem = this.renderItem(item);
      menuList.appendChild(menuItem);
    }
    this.container.appendChild(menuList);
  }
  renderItem(item) {
    let menuItem = document.createElement('li');
    let link = document.createElement('a');
    link.href = '#';
    link.innerText = item.name;
    menuItem.appendChild(link);
    if (item.children.length > 0) {
      let submenu = document.createElement('ul');
      for (let child of item.children) {
        let subMenuItem = this.renderItem(child);
        submenu.appendChild(subMenuItem);
      }
      menuItem.appendChild(submenu);
    }
    link.addEventListener('click', (event) => {
      event.preventDefault();
      if (item.state) {
        item.close();
        menuItem.classList.remove('open');
      } else {
        item.open();
        menuItem.classList.add('open');
      }
    });
    if (item.state) {
      menuItem.classList.add('open');
    }
    return menuItem;
  }
}

通过定义Menu和MenuItem类,我们可以很方便地添加子菜单项,同时也可以处理多级嵌套的情况。在这个例子中,我们可以通过以下代码调用Menu类:

let menu = new Menu(document.querySelector('.menu'));
let menuItem1 = new MenuItem(1, '菜单1');
menuItem1.addChildren(new MenuItem(11, '子菜单1-1'));
menuItem1.addChildren(new MenuItem(12, '子菜单1-2'));
let menuItem2 = new MenuItem(2, '菜单2');
menuItem2.addChildren(new MenuItem(21, '子菜单2-1'));
menuItem2.addChildren(new MenuItem(22, '子菜单2-2'));
let menuItem3 = new MenuItem(3, '菜单3');
menuItem3.addChildren(new MenuItem(31, '子菜单3-1'));
menuItem3.addChildren(new MenuItem(32, '子菜单3-2'));
menu.addMenuItem(menuItem1);
menu.addMenuItem(menuItem2);
menu.addMenuItem(menuItem3);
menu.render();

通过这些代码,我们可以得到一个基本的两级嵌套的折叠菜单。

示例2

假设我们要实现一个三级嵌套的折叠菜单,包含三个顶级菜单项,每个顶级菜单项下面的两个子菜单项,每个子菜单项下面的两个子菜单项,在一般方法中,我们可以定义如下的菜单结构:

<div class="menu">
  <ul>
    <li><a href="#">菜单1</a>
      <ul>
        <li><a href="#">子菜单1-1</a>
          <ul>
            <li><a href="#">子菜单1-1-1</a></li>
            <li><a href="#">子菜单1-1-2</a></li>
          </ul>
        </li>
        <li><a href="#">子菜单1-2</a>
          <ul>
            <li><a href="#">子菜单1-2-1</a></li>
            <li><a href="#">子菜单1-2-2</a></li>
          </ul>
        </li>
      </ul>
    </li>
    <li><a href="#">菜单2</a>
      <ul>
        <li><a href="#">子菜单2-1</a>
          <ul>
            <li><a href="#">子菜单2-1-1</a></li>
            <li><a href="#">子菜单2-1-2</a></li>
          </ul>
        </li>
        <li><a href="#">子菜单2-2</a>
          <ul>
            <li><a href="#">子菜单2-2-1</a></li>
            <li><a href="#">子菜单2-2-2</a></li>
          </ul>
        </li>
      </ul>
    </li>
    <li><a href="#">菜单3</a>
      <ul>
        <li><a href="#">子菜单3-1</a>
          <ul>
            <li><a href="#">子菜单3-1-1</a></li>
            <li><a href="#">子菜单3-1-2</a></li>
          </ul>
        </li>
        <li><a href="#">子菜单3-2</a>
          <ul>
            <li><a href="#">子菜单3-2-1</a></li>
            <li><a href="#">子菜单3-2-2</a></li>
          </ul>
        </li>
      </ul>
    </li>
  </ul>
</div>

在改写成面向对象方法时,我们只需要稍微修改一下MenuItem类中的addChildren方法,其他部分大体相同:

class MenuItem {
  constructor(id, name) {
    this.id = id;
    this.name = name;
    this.state = false;
    this.children = [];
  }
  addChildren(child) {
    this.children.push(child);
    child.parent = this;
  }
  open() {
    this.state = true;
  }
  close() {
    this.state = false;
  }
}

class Menu {
  constructor(container) {
    this.container = container;
    this.root = [];
  }
  addMenuItem(item) {
    this.root.push(item);
  }
  render() {
    let menuList = document.createElement('ul');
    for (let item of this.root) {
      let menuItem = this.renderItem(item);
      menuList.appendChild(menuItem);
    }
    this.container.appendChild(menuList);
  }
  renderItem(item) {
    let menuItem = document.createElement('li');
    let link = document.createElement('a');
    link.href = '#';
    link.innerText = item.name;
    menuItem.appendChild(link);
    if (item.children.length > 0) {
      let submenu = document.createElement('ul');
      for (let child of item.children) {
        let subMenuItem = this.renderItem(child);
        submenu.appendChild(subMenuItem);
      }
      menuItem.appendChild(submenu);
    }
    link.addEventListener('click', (event) => {
      event.preventDefault();
      if (item.state) {
        item.close();
        menuItem.classList.remove('open');
      } else {
        item.open();
        menuItem.classList.add('open');
      }
    });
    if (item.state) {
      menuItem.classList.add('open');
    }
    return menuItem;
  }
}

通过定义修改后的MenuItem类,我们可以很方便地处理多级嵌套的菜单项,同时也可以通过parent属性访问上一级菜单项的信息。在这个例子中,我们可以通过以下代码调用Menu类:

let menu = new Menu(document.querySelector('.menu'));
let menuItem1 = new MenuItem(1, '菜单1');
let menuItem11 = new MenuItem(11, '子菜单1-1');
let menuItem111 = new MenuItem(111, '子菜单1-1-1');
let menuItem112 = new MenuItem(112, '子菜单1-1-2');
let menuItem12 = new MenuItem(12, '子菜单1-2');
let menuItem121 = new MenuItem(121, '子菜单1-2-1');
let menuItem122 = new MenuItem(122, '子菜单1-2-2');
menuItem11.addChildren(menuItem111);
menuItem11.addChildren(menuItem112);
menuItem12.addChildren(menuItem121);
menuItem12.addChildren(menuItem122);
menuItem1.addChildren(menuItem11);
menuItem1.addChildren(menuItem12);
let menuItem2 = new MenuItem(2, '菜单2');
let menuItem21 = new MenuItem(21, '子菜单2-1');
let menuItem211 = new MenuItem(211, '子菜单2-1-1');
let menuItem212 = new MenuItem(212, '子菜单2-1-2');
let menuItem22 = new MenuItem(22, '子菜单2-2');
let menuItem221 = new MenuItem(221, '子菜单2-2-1');
let menuItem222 = new MenuItem(222, '子菜单2-2-2');
menuItem21.addChildren(menuItem211);
menuItem21.addChildren(menuItem212);
menuItem22.addChildren(menuItem221);
menuItem22.addChildren(menuItem222);
menuItem2.addChildren(menuItem21);
menuItem2.addChildren(menuItem22);
let menuItem3 = new MenuItem(3, '菜单3');
let menuItem31 = new MenuItem(31, '子菜单3-1');
let menuItem311 = new MenuItem(311, '子菜单3-1-1');
let menuItem312 = new MenuItem(312, '子菜单3-1-2');
let menuItem32 = new MenuItem(32, '子菜单3-2');
let menuItem321 = new MenuItem(321, '子菜单3-2-1');
let menuItem322 = new MenuItem(322, '子菜单3-2-2');
menuItem31.addChildren(menuItem311);
menuItem31.addChildren(menuItem312);
menuItem32.addChildren(menuItem321);
menuItem32.addChildren(menuItem322);
menuItem3.addChildren(menuItem31);
menuItem3.addChildren(menuItem32);
menu.addMenuItem(menuItem1);
menu.addMenuItem(menuItem2);
menu.addMenuItem(menuItem3);
menu.render();

通过这些代码,我们可以得到一个基本的三级嵌套的折叠菜单。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:js一般方法改写成面向对象方法的无限级折叠菜单示例代码 - Python技术站

(0)
上一篇 2023年6月8日
下一篇 2023年6月8日

相关文章

  • JS解决 Array.fill()参数为对象指向同一个引用地址的问题

    JS中,数组的fill()方法可以用来将一个固定值填充到数组中的每一个元素上。但是当传递的参数为对象时,会出现指向同一个引用地址的问题。因此,为了解决这个问题,我们可以采取以下几种方案。 方案一:使用 ES6 中的 Array.from() 方法 在 ES6 中,Array.from() 方法可以将任何可迭代对象转换为一个数组。因此,我们可以先使用该方法生成…

    node js 2023年6月8日
    00
  • js获取多个tagname的节点数组

    获取多个tagname的节点数组在 JavaScript 中非常常见,通常可以通过 document.getElementsByTagName() 方法来实现。 该方法接收一个 tagName 参数,返回一个包含所有指定 tagName 的元素节点列表。 以下是一个基本示例,演示如何使用 document.getElementsByTagName() 方法获…

    node js 2023年6月8日
    00
  • 美团Java实习招聘面试经历总结【已拿到Offer】

    下面就来详细讲解“美团Java实习招聘面试经历总结【已拿到Offer】”的攻略: 核心经验 在做美团Java实习招聘面试准备时,主要需要掌握以下几个核心经验: 1. Java基础知识全面掌握 Java是美团面试Java实习时重点考察的知识点,要想顺利通过面试,首先需要掌握Java的基础知识,包括Java的数据类型、流程控制、面向对象编程、异常处理等等。此外,…

    node js 2023年6月8日
    00
  • 使用 NodeJS+Express 开发服务端的简单介绍

    下面就是使用 NodeJS+Express 开发服务端的简单攻略。 简介 NodeJS 是一种运行在服务器端的 JavaScript 运行环境,它允许开发者使用 JavaScript 编写后端服务。而 Express 是 NodeJS 应用最广泛的web应用程序框架之一,它提供了一些简洁的方法来处理 http 请求、路由等任务。使用 NodeJS+Expre…

    node js 2023年6月8日
    00
  • Nodejs模块载入运行原理

    一、Nodejs模块载入 Nodejs模块载入指的是当需要使用模块时,Nodejs会通过一定的方式找到对应的模块文件,载入这个模块,并在当前的上下文环境中运行该模块。 二、Nodejs模块化 Nodejs支持模块化编程,这意味着一个功能被拆分成多个文件,每个文件都是一个模块,在程序中需要使用该功能时,只需要加载这个模块即可,避免了单一文件过大、难于维护的问题…

    node js 2023年6月8日
    00
  • nodejs事件的监听与触发的理解分析

    Node.js是基于事件驱动的异步编程,使用事件可以让不同的模块进行通信,从而对系统进行解耦。与其他编程语言相比,Node.js的事件模型具有高效、简明、易用等特点。本文将详细讲解Node.js中事件的监听与触发的理解分析。 事件监听 事件监听是指程序监听某个事件的发生,当这个事件发生时,程序会执行相应的回调函数。Node.js中可以使用eventEmitt…

    node js 2023年6月8日
    00
  • 关于node+mysql数据库连接池连接

    我来为你讲解一下关于node.js和mysql数据库连接池连接的完整攻略。 1. 安装 mysql 模块 我们需要先安装mysql模块来连接mysql数据库,输入以下命令来安装: npm install mysql 2. 创建连接池 接下来,我们需要创建数据库连接池,并配置连接数据库的信息,如下所示: const mysql = require(‘mysql…

    node js 2023年6月8日
    00
  • javascript 冒泡排序 正序和倒序实现代码

    冒泡排序是一种简单的排序算法,其基本思想是通过比较相邻元素的大小进行排序。在一个数组中,每次比较都会将相邻元素中较大的元素向右移动。重复此过程直到整个数组都按从小到大的顺序排列。 以下是 JavaScript 冒泡排序的正序实现代码: function bubbleSort(arr) { for (let i = 0; i < arr.length -…

    node js 2023年6月8日
    00
合作推广
合作推广
分享本页
返回顶部