从问题到源码-orgchart

218 阅读2分钟

起因

实现一个部门组织树展示,点击部门进行请求,重新渲染上下路径,并且高亮选中部门。

选型

优势劣势
orgchart1. dom结构,node样式自定义
2.使用ul嵌套实现,舍弃了table
3.所有事件齐全
4.包稳定
1. 放大缩小失真
2.多版本(vue,react)都是多年不更新。
3. 默认最新最全的包是jq版本
d3-org-chart1. 天然具备svg优势
2. 事件基本齐全
3.依赖d3,代码实现清晰,易读
1. node样式定义需要html直接写没有提示d3.html(代码块)
2. 库只配置node点击事件,伸缩事件,自行添加事件基本不可能。

无论哪一个都不能实现拿来就用主义,所以采用d3-org-chart后续进行二次开发也比较方便(节点的形态针对多个业务也相对固定)。

实现分析

orgchart.png

  1. 实现选中高亮
 nodeUpdate: function (d, i, arr) {
                d3.select(this)
                    .select('.node-rect')
                    .attr("stroke", d => d.data._highlighted || d.data._upToTheRootHighlighted ? '#152785' : 'none')
                    .attr("stroke-width", d.data._highlighted || d.data._upToTheRootHighlighted ? 10 : 1)
            }

库本身具有的highlighted是写死的,所以不具备配置属性,但是通过阅读源码我们发现node传入的相关属性是会被保留,并且具有click事件配置。所以我们能自行实现效果

       .onNodeClick((id) => {
          const mark = data.find((item) => item.xx === id)
          mark._active = true
        })
       .nodeContent(function (d, i, arr, state) {
        const color = '#FFFFFF'
        return `
            <div style="font-family: 'Inter', sans-serif;background-color:${color};margin-top:-1px; margin-left:-1px;width:${d.width}px;height:${d.height}px;border-radius:10px;border: 1px solid ${d.data._active ? '#7d4be1' : '#E4E2E9'}">
           </div>`
      })
  1. 实现点击node实现重新渲染
    通过阅读源码我们发现node展开层级实际上也是调用了updateNodesState这个方法来重新渲染。 所以我们也只需要做同样的事情,通过绑定新数据,触发重新渲染即可
实例.onNodeClick((id) => {
    实例.data(new data)
    实例.updateNodesState()
})

效果

Untitled.gif

总结

读源码的意义,在于解决问题,学习结构,并且排除隐患。这次通过解读源码我们实现了业务需求,节省了大量时间可以有意义的摸鱼。通过阅读这个库我们可以发现,d3对于封装的细致程度,只需要选对布局算法,绑定事件以及编写d3都提供了极大的便利。

reference

  1. bumbeishvili.medium.com/introducing…