起因
实现一个部门组织树展示,点击部门进行请求,重新渲染上下路径,并且高亮选中部门。
选型
包 | 优势 | 劣势 |
---|---|---|
orgchart | 1. dom结构,node样式自定义 2.使用ul嵌套实现,舍弃了table 3.所有事件齐全 4.包稳定 | 1. 放大缩小失真 2.多版本(vue,react)都是多年不更新。 3. 默认最新最全的包是jq版本 |
d3-org-chart | 1. 天然具备svg优势 2. 事件基本齐全 3.依赖d3,代码实现清晰,易读 | 1. node样式定义需要html直接写没有提示d3.html(代码块) 2. 库只配置node点击事件,伸缩事件,自行添加事件基本不可能。 |
无论哪一个都不能实现拿来就用主义,所以采用d3-org-chart后续进行二次开发也比较方便(节点的形态针对多个业务也相对固定)。
实现分析
- 实现选中高亮
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>`
})
- 实现点击node实现重新渲染
通过阅读源码我们发现node展开层级实际上也是调用了updateNodesState这个方法来重新渲染。 所以我们也只需要做同样的事情,通过绑定新数据,触发重新渲染即可
实例.onNodeClick((id) => {
实例.data(new data)
实例.updateNodesState()
})
效果
总结
读源码的意义,在于解决问题,学习结构,并且排除隐患。这次通过解读源码我们实现了业务需求,节省了大量时间可以有意义的摸鱼。通过阅读这个库我们可以发现,d3对于封装的细致程度,只需要选对布局算法,绑定事件以及编写d3都提供了极大的便利。