惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The Register - Security
The Register - Security
T
Troy Hunt's Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cybersecurity and Infrastructure Security Agency CISA
S
Securelist
G
GRAHAM CLULEY
S
Schneier on Security
S
Secure Thoughts
Know Your Adversary
Know Your Adversary
Forbes - Security
Forbes - Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
The Hacker News
The Hacker News
Y
Y Combinator Blog
L
LINUX DO - 最新话题
D
Docker
S
Security @ Cisco Blogs
P
Proofpoint News Feed
V
Vulnerabilities – Threatpost
博客园_首页
T
The Blog of Author Tim Ferriss
Blog — PlanetScale
Blog — PlanetScale
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
V2EX - 技术
V2EX - 技术
NISL@THU
NISL@THU
MongoDB | Blog
MongoDB | Blog
阮一峰的网络日志
阮一峰的网络日志
P
Privacy & Cybersecurity Law Blog
C
Cisco Blogs
AWS News Blog
AWS News Blog
博客园 - 司徒正美
Martin Fowler
Martin Fowler
W
WeLiveSecurity
月光博客
月光博客
博客园 - 聂微东
N
News and Events Feed by Topic
Google DeepMind News
Google DeepMind News
D
DataBreaches.Net
T
Tenable Blog
IT之家
IT之家
MyScale Blog
MyScale Blog
N
Netflix TechBlog - Medium
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 三生石上(FineUI控件)
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
B
Blog
量子位
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
N
News and Events Feed by Topic
Vercel News
Vercel News

青空之蓝

[青空之蓝-2023] - 色彩 | 青空之蓝 [青空之蓝-2022] - 平静 | 青空之蓝 [青空之蓝-2021] - 远望 | 青空之蓝 浅谈垃圾回收 | 青空之蓝 浅谈泛型擦除 | 青空之蓝 浅谈单点登录 | 青空之蓝 使用 Kotlin 编写 Spring 测试 | 青空之蓝 设计模式系列文章 | 青空之蓝 从零实现一个 Java 微框架 - IoC | 青空之蓝 从零实现一个 Java 微框架 - 前言 | 青空之蓝 浅谈 JVM:类加载 | 青空之蓝 浅谈 IO | 青空之蓝 浅谈并发:synchronized & ReentrantLock | 青空之蓝 浅谈并发:CAS & AQS | 青空之蓝 浅谈并发:ThreadLocal | 青空之蓝 浅谈并发:三大特性 | 青空之蓝 浅谈组合注解 & 注解别名 | 青空之蓝 [青空之蓝-2020]-迷茫 | 青空之蓝 Java 系列文章 | 青空之蓝 HTTP 系列文章 | 青空之蓝 浅谈 EatWhatYouKill | 青空之蓝 浅谈可扩展线程池 | 青空之蓝 聊聊写框架 | 青空之蓝 聊聊现状-[2020-09] | 青空之蓝 浅谈并发:锁 | 青空之蓝 浅谈并发:基础 | 青空之蓝 浅谈缓存 | 青空之蓝 无须定义类,Spring 快速注入 Json 参数 | 青空之蓝 浅谈 Proxy 和 Aop | 青空之蓝 从零实现一个 PHP 微框架 - 初始化请求 | 青空之蓝 为 Vue3 添加一个简单的 Store | 青空之蓝 从零实现一个 PHP 微框架 - 服务提供者 | 青空之蓝 WSL2 踩坑记录 | 青空之蓝 浅谈浏览器Event Loop [更新] | 青空之蓝 从零实现一个 PHP 微框架 - Bootstrap 启动加载 | 青空之蓝 从零实现一个 PHP 微框架 - IoC 容器 | 青空之蓝 从零实现一个 PHP 微框架 - PSR & Composer | 青空之蓝 从零实现一个 PHP 微框架 - 前言 | 青空之蓝 MVVM 简单实现 | 青空之蓝 浅谈 DI 和 IoC | 青空之蓝 中间件实现 [PHP] | 青空之蓝 告别 Windows 终端的难看难用,打造好用的 PowerShell | 青空之蓝 VSCode Java输出中文乱码问题解决[更新] | 青空之蓝 浅谈浏览器渲染 | 青空之蓝 Vue-Cli@2 项目迁移日志 | 青空之蓝 Laragon & Scoop 集成踩坑记录 | 青空之蓝 「一行代码」优雅管理 Windows 软件 | 青空之蓝 [青空之蓝-2019]-年度总结 | 青空之蓝 为Vue添加简单的Store | 青空之蓝 为React添加简单的Store | 青空之蓝 为Vuex添加同步Action | 青空之蓝 浅谈B+树 | 青空之蓝 浅谈跳表 | 青空之蓝 浅谈数据库索引 | 青空之蓝 MySQL事务隔离 | 青空之蓝 算法复杂度分析(1) | 青空之蓝 一年来的经验总结 | 青空之蓝 Acrylic - VSCode Extension | 青空之蓝 ace编辑器设置惯性滚动 | 青空之蓝 Java二叉树实现 | 青空之蓝 Java图实现 | 青空之蓝 为apt方式安装的nginx重新编译增加WebDAV | 青空之蓝 XK-Editor - 一个支持富文本和Markdown的编辑器 | 青空之蓝 Laravel生成目录树 | 青空之蓝 XK-Note - 集各种神奇功能的云笔记 | 青空之蓝 PHP GD生成验证码 | 青空之蓝 PHP GD图片处理[转换格式-水印-缩略图] | 青空之蓝 Origami - 简洁轻快的WordPress主题 | 青空之蓝 为WordPress启用WorkBox | 青空之蓝 [青空之蓝-2018]-年度总结 | 青空之蓝 VSCode Java手动导入jar和源码包 | 青空之蓝 Windows IP变化自动发送邮件 | 青空之蓝 C链表实现重制版 | 青空之蓝 C 结构体的定义和使用 | 青空之蓝 图的搜索(遍历) - BFS & DFS | 青空之蓝 Java链表实现 | 青空之蓝 C 快速排序 | 青空之蓝 C 插入排序 | 青空之蓝 C 归并排序 | 青空之蓝 C语言链表实现 | 青空之蓝 VSCode配置Java调试环境[Windows] | 青空之蓝 C 选择排序 | 青空之蓝 C 冒泡排序 | 青空之蓝 VSCode配置PHP调试环境[Windows] | 青空之蓝 VSCode配置C/C++ GDB调试环境[Windows] | 青空之蓝 WordPress友情链接模板 | 青空之蓝 Intel Optane 傲腾内存体验 | 青空之蓝 Mysql双机热备实战 | 青空之蓝 博客一年记录 | 青空之蓝 为WordPress启用Service Worker | 青空之蓝 Bing每日一图API | 青空之蓝 iframe延迟加载 | 青空之蓝 写在2018年高考前 | 青空之蓝 The Fox主题汉化分享 | 青空之蓝 [青空之蓝-2017]-崭新 | 青空之蓝 本博客评论规则 | 青空之蓝 世界,您好! | 青空之蓝
JS生成列表树 | 青空之蓝
Otstar Lin · 2019-04-19 · via 青空之蓝

上一篇文章我们使用 PHP 的构建简单的目录树,这次由于一个项目的需要(构建标题大纲),需要在前端使用 JS 构建 ul li 的多层次列表,其实就是类似于 ZUI 的树形菜单啦( ̄ ▽  ̄)"

实现原理

首先需要准备一个对象数组,数组中的对象拥有leveltitle(可以自行命名,由于博主是生成标题的索引所以就使用 title 命名)

另外,该数组需要按一定的顺序进行排序,否则就需要自行设置索引,排序的规则是子级必须紧跟在父级后,例如

// # 1
// ## 2
// ## 3
// ### 4
// ### 5
// # 6

var tocContent = [
  {
    level: 1,
    title: "1",
  },
  {
    level: 2,
    title: "2",
  },
  {
    level: 2,
    title: "3",
  },
  {
    level: 3,
    title: "4",
  },
  {
    level: 3,
    title: "5",
  },
  {
    level: 1,
    title: "6",
  },
];
// # 1
// ## 2
// ## 3
// ### 4
// ### 5
// # 6

var tocContent = [
  {
    level: 1,
    title: "1",
  },
  {
    level: 2,
    title: "2",
  },
  {
    level: 2,
    title: "3",
  },
  {
    level: 3,
    title: "4",
  },
  {
    level: 3,
    title: "5",
  },
  {
    level: 1,
    title: "6",
  },
];

有了目录的对象数组,我们就可以通过递归或者栈来构建列表树了

实现代码

构建 HTML

var tocContent = [];
function getTocHtml() {
  var html = getTocHtmlTree(0, "");
  window.$toc = html;
  return html;
}
function getTocHtmlTree(index, str) {
  if (index >= tocContent.length) return str;
  if (index == 0) {
    str += "";
  } else if (tocContent[index].level > tocContent[index - 1].level) {
    for (let i = tocContent[index - 1].level; i < tocContent[index].level; i++) {
      str += "<ul>";
    }
  } else if (tocContent[index].level < tocContent[index - 1].level) {
    for (let i = tocContent[index].level; i < tocContent[index - 1].level; i++) {
      str += "</ul></li>";
    }
  } else {
    str += "</li>";
  }
  str +=
    '<li><img class="toc-img" src="/static/svg/disc.svg"><a href="#' +
    tocContent[index].title
      .toLowerCase()
      .replace(/ /g, "-")
      .replace(/[^\u4e00-\u9fa5a-zA-Z0-9-]/g, "") +
    '">' +
    tocContent[index].title +
    "</a>";
  return getTocHtmlTree(index + 1, str);
}
var tocContent = [];
function getTocHtml() {
  var html = getTocHtmlTree(0, "");
  window.$toc = html;
  return html;
}
function getTocHtmlTree(index, str) {
  if (index >= tocContent.length) return str;
  if (index == 0) {
    str += "";
  } else if (tocContent[index].level > tocContent[index - 1].level) {
    for (let i = tocContent[index - 1].level; i < tocContent[index].level; i++) {
      str += "<ul>";
    }
  } else if (tocContent[index].level < tocContent[index - 1].level) {
    for (let i = tocContent[index].level; i < tocContent[index - 1].level; i++) {
      str += "</ul></li>";
    }
  } else {
    str += "</li>";
  }
  str +=
    '<li><img class="toc-img" src="/static/svg/disc.svg"><a href="#' +
    tocContent[index].title
      .toLowerCase()
      .replace(/ /g, "-")
      .replace(/[^\u4e00-\u9fa5a-zA-Z0-9-]/g, "") +
    '">' +
    tocContent[index].title +
    "</a>";
  return getTocHtmlTree(index + 1, str);
}

通过调用getTocHtml()就可以获得目录的 HTML,生成后的效果如下

从代码中可以看到在 li 标签中还有img标签和带锚点的a标签,a 标签是为了跳转到指定位置而设置的,可以按不同的需求进行调整,img 标签是为了点击时显示和隐藏子级列表而设置的

为目录添加 toggle 功能

废话不多说,先上代码

function initTocTree() {
    var items = document.querySelectorAll('#toc .toc-img ~ ul') for (let i = 0; i < items.length; i++) {
        items[i].parentNode.children[0].setAttribute('src', '/static/svg/minus-square.svg');
        items[i].parentNode.children[0].setAttribute('onclick', 'toggleToc(this)');
    }
}
function toggleToc(ele) {
    var display = ele.nextElementSibling.nextElementSibling.style.display
    if (display === '' || display === 'block') {
        ele.nextElementSibling.nextElementSibling.style.display = 'none';
        ele.setAttribute('src', '/static/svg/plus-square.svg');
    } else {
        ele.nextElementSibling.nextElementSibling.style.display = 'block';
        ele.setAttribute('src', '/static/svg/minus-square.svg');
    }
}
function initTocTree() {
    var items = document.querySelectorAll('#toc .toc-img ~ ul') for (let i = 0; i < items.length; i++) {
        items[i].parentNode.children[0].setAttribute('src', '/static/svg/minus-square.svg');
        items[i].parentNode.children[0].setAttribute('onclick', 'toggleToc(this)');
    }
}
function toggleToc(ele) {
    var display = ele.nextElementSibling.nextElementSibling.style.display
    if (display === '' || display === 'block') {
        ele.nextElementSibling.nextElementSibling.style.display = 'none';
        ele.setAttribute('src', '/static/svg/plus-square.svg');
    } else {
        ele.nextElementSibling.nextElementSibling.style.display = 'block';
        ele.setAttribute('src', '/static/svg/minus-square.svg');
    }
}

initTocTree()是用来初始化列表树的,该函数会修改有子列表点的父级列表图片,并为其添加 onclick 事件,toggleToc()是在 img 标签被点击的时候展开/隐藏子级列表的,同时修改其 img 图像,便于用户判断子列表是否已经展开,具体效果如下

虽然有上篇文章的参考我还是想了很久,写出来的代码也很渣,看来还需不断的学习啊>﹏<

JS生成列表树

https://blog.ixk.me/post/js-generate-list-tree
  • 许可协议

    BY-NC-SA

  • 本文作者

    Otstar Lin

  • 发布于

    2019/04/19

转载或引用本文时请遵守许可协议,注明出处、不得用于商业用途!

XK-Editor - 一个支持富文本和Markdown的编辑器Laravel生成目录树