npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

cool-tree-tool

v1.1.8

Published

为Javascript操作树结构数据提供的一些便捷接口

Downloads

2

Readme

JS树结构数据处理工具

一、简介

tree-tool是一个用于处理js树结构的一些函数,无任何依赖,体积非常小。

其实代码本身很简单,但是因为问我的同学太多了,加之我在好几个项目需要用到几乎完全相同的代码,我就写了些非常通用的函数收集在这个库里。

二、安装

#使用yarn
yarn add cool-tree-tool
#使用npm
npm install cool-tree-tool

三、使用

引入

// commonjs
const treeTool = require('tree-tool')

// esm
import treeTool from 'tree-tool'

// 通过html标签引入
<script src="https://unpkg.com/tree-tool/dist/index.js"></script>
// 加载完成后会有属性window.treeTool

API说明

| 功能 | API | 用到的config配置项 | 备注 | | ---- | :----: | :----: | :----: | | 列表结构转树结构 | treeTool.fromList(list[, config]) | id、pid、children | | | 树结构转列表结构 | treeTool.toList(tree[, config] ) | children | | | 查找符合条件的单个节点 | treeTool.findNode(tree, callback[, config]) | children | 返回广度优先遍历查找到的第一个符合条件(callback(node)为true)的节点,没有则返回null | | 查找符合条件的所有节点 | treeTool.findNodeAll(tree, callback[, config]) | children | | | 查找符合条件的单个节点的路径 | treeTool.findPath(tree, callback[, config]) | children| 返回符合条件(callback(node)为true)的节点的所有祖先节点有序组成的数组,没有找到节点则返回null | | 查找符合条件的所有节点的路径 | treeTool.findPathAll(tree, callback[, config]) | children | 返回符合条件(callback(node)为true)的节点路径组成的数组 | | 树结构筛选 | treeTool.filter(tree, callback[, config]) | children | 返回符合筛选条件(callback(node)为true)的树节点构成的树,一个节点符合条件,其祖先节点也会被保留返回 | | 树结构遍历 | treeTool.forEach(tree, callback[, config]) | children | 对于所有节点node调用callback(node),深度优先 | | 在指定oldNode前插入newNode | treeTool.insertBefore (tree, newNode, oldNode[, config]) | children | 如果树中没有oldNode,则不会改变原数组。注意oldNode和newNode的参数顺序,和它们在树中的顺序一致 | | 在指定oldNode后插入newNode | treeTool.insertAfter (tree, oldNode, newNode[, config]) | children | 如果树中没有oldNode,则不会改变原数组。注意oldNode和newNode的参数顺序,和它们在树中的顺序一致 | | 删除符合条件的所有节点 | treeTool.removeNode(tree, callback[, config]) | children | 删除符合条件(callback(node)为true)的所有节点及其子节点 | | 创建闭包了配置项config的实例 | treeTool.createInstance(config) | 无 | 为了避免每个函数都传入config参数,你可以使用该API创建一个实例,以上所有API可以当成实例方法使用 |

参数说明:

1. list 列表 给定一组node节点列表,每个node节点至少包含两个属性:唯一标识和父节点标识,例如:

const list = [
  { id: '1', title: '节点1', parentId: '', },
  { id: '1-1', title: '节点1-1', parentId: '1' },
  { id: '1-2', title: '节点1-2', parentId: '1' },
  { id: '2', title: '节点2', parentId: '' },
  { id: '2-1', title: '节点2-1', parentId: '2' }
]

2. tree 树结构数据 一个数组表示的一棵树,例如:

const tree = [
  {
    id: '1',
    title: '节点1',
    children: [
      {
        id: '1-1',
        title: '节点1-1'
      },
      {
        id: '1-2',
        title: '节点1-2',
        children: [
          {
            id: '1-2-1',
            title: '节点1-2-1'
          }
        ]
      }
    ]
  },
  {
    id: '2',
    title: '节点2',
    children: [
      {
        id: '2-1',
        title: '节点2-1'
      }
    ]
  }
]

3. callback 回调函数,接收node参数,在查找、筛选等功能中表示约束条件,在遍历功能中则为对每个节点的操作。

4. config 可选,用于自定义node节点的唯一标识、父节点、子节点的属性名称,如果接口用到的config配置项与默认不同,需要通过config参数来自定义不同的部分。默认值如下:

{
  id: 'id', // 唯一标识属性名
  children: 'children', // 子节点属性名
  pid: 'pid' // 父节点标识属性名
}

四、使用示例

const tree = require('./index')

function getTree () {
  const tree = [
    {
      id: '1',
      title: '节点1',
      children: [
        {
          id: '1-1',
          title: '节点1-1'
        },
        {
          id: '1-2',
          title: '节点1-2',
          children: [
            {
              id: '1-2-1',
              title: '节点1-2-1'
            }
          ]
        }
      ]
    },
    {
      id: '2',
      title: '节点2',
      children: [
        {
          id: '2-1',
          title: '节点2-1'
        }
      ]
    }
  ]
  return tree
}

function getList () {
  const list = [
    {
      id: '1',
      title: '节点1',
      parentId: '',
    },
    {
      id: '1-1',
      title: '节点1-1',
      parentId: '1'
    },
    {
      id: '1-2',
      title: '节点1-2',
      parentId: '1'
    },
    {
      id: '2',
      title: '节点2',
      parentId: ''
    },
    {
      id: '2-1',
      title: '节点2-1',
      parentId: '2'
    }
  ]
  return list
}


// 创建一个实例,因为数据里的pid属性名与默认值不同,所以需要传递该配置项
const instance = tree.createInstance({ pid: 'parentId' })

// 列表转树 不创建实例
function testFromList () {
  const list = getList()
  const tree = tree.fromList(list, { pid: 'parentId' })
  console.log(JSON.stringify(tree, null, 2))
}

// 列表结构转树 使用instance
function testFromList () {
  const list = getList()
  const tree = instance.fromList(list)
  console.log(JSON.stringify(tree, null, 2))
}

// 树结构转列表结构
function testToList () {
  const tree = getTree()
  const list = instance.toList(tree)
  console.log(list.map(i => i.id))
}

// 查找节点
function testFindNode () {
  const callback = node => node.id == '2-1'
  const tree = getTree()
  const result = instance.findNode(tree, callback)
  console.log(JSON.stringify(result, null, 2))
}

// 查找符合条件的所有节点
function testFindNodeAll () {
  const list = getList()
  const tree = instance.fromList(list)
  
  const callback = node => node.parentId == '1'
  const result = instance.findNodeAll(tree, callback)
  console.log(JSON.stringify(result, null, 2))
}

// 查找节点路径
function testFindPath () {
  const callback = node => node.id == '2-1'
  const tree = getTree()
  const result = instance.findPath(tree, callback)
  console.log(result.map(i => i.id))
}

// 查找符合条件的所有节点的路径
function testFindPathAll () {
  const callback = node => node.id == '2-1' || node.id == '1-2-1'
  const tree = getTree()
  const result = instance.findPathAll(tree, callback)
  console.log(result)
}

// 树节点过滤
function testFilter () {
  const callback = node => node.id == '2-1'
  const tree = getTree()
  const result = instance.filter(tree, callback)
  console.log(JSON.stringify(result, null, 2))
}

// 树节点遍历 深度优先
function testForEach () {
  const tree = getTree()
  const idList = []
  instance.forEach(tree, node => idList.push(node.id))
  console.log(idList)
}

// 节点插入:在node前插入newNode
function testInsertBefore () {
  const tree = getTree()
  const node = instance.findNode(tree, n => n.id == '1-2-1')
  const newNode = {
    id: '1-2-0',
    title: '节点1-2-0'
  }
  instance.insertBefore(tree, newNode, node)
  const idList = []
  instance.forEach(tree, node => idList.push(node.id))
  console.log(idList)
}

// 节点插入:在node后插入newNode
function testInsertAfter () {
  const tree = getTree()
  const node = instance.findNode(tree, n => n.id == '1-2-1')
  const newNode = {
    id: '1-2-2',
    title: '节点1-2-2'
  }
  instance.insertAfter(tree, node, newNode)
  const idList = []
  instance.forEach(tree, node => idList.push(node.id))
  console.log(idList)
}

// 节点删除:删除符合条件的Node
function testRemoveNode () {
  const tree = getTree()
  instance.removeNode(tree, n => n.id == '1')
  console.log(tree)
}

联系我

使用过程中有任何问题,请联系我:

Email: [email protected]

wechat: win_tc


有BUG或新需求

欢迎在issue提树结构相关的新需求或者本库的BUG,以帮助我完善这个小树库,感谢。

您也可以通过PR参与完善,非常感谢。