Vue2项目实战:用AntV G6打造可折叠树形结构(附完整代码)
Vue2与AntV G6深度整合构建企业级可交互树形可视化方案在数据密集型的现代Web应用中树形结构可视化已成为组织架构展示、文件目录管理、决策流程分析等场景的核心需求。本文将基于Vue2框架与AntV G6可视化引擎从工程化角度完整呈现一个支持动态折叠展开、节点自定义渲染的企业级树形结构解决方案。1. 环境搭建与基础配置1.1 初始化Vue2项目首先确保已安装Node.js环境建议版本12通过Vue CLI创建项目npm install -g vue/cli vue create g6-tree-demo cd g6-tree-demo安装AntV G6核心库及扩展插件npm install antv/g6 antv/hierarchy --save1.2 基础组件结构创建TreeGraph.vue组件文件建立基础DOM结构和引入逻辑template div classtree-container div refgraphContainer :style{ height: containerHeight px }/div /div /template script import G6 from antv/g6 import { TreeGraph } from antv/g6 export default { name: TreeGraph, props: { treeData: { type: Object, required: true } }, data() { return { graph: null, containerHeight: 500 } }, mounted() { this.initGraph() } } /script2. 数据规范与预处理2.1 标准树形数据结构AntV G6要求的树形数据格式如下{ id: root, label: 根节点, children: [ { id: child1, label: 子节点1, children: [...] } ] }2.2 数据清洗策略实际业务数据往往需要转换处理推荐使用以下工具方法methods: { normalizeTreeData(rawData) { const processNode (node) { if (!node) return null return { id: node.id || Math.random().toString(36).substr(2, 9), label: node.name || node.title || 未命名节点, children: Array.isArray(node.children) ? node.children.map(processNode).filter(Boolean) : [], ...node // 保留原始属性 } } return processNode(rawData) } }3. 核心可视化实现3.1 图形实例化配置在initGraph方法中配置TreeGraph的核心参数initGraph() { this.graph new TreeGraph({ container: this.$refs.graphContainer, width: this.$el.clientWidth, height: this.containerHeight, modes: { default: [drag-node] }, defaultNode: { type: custom-node, size: [120, 40], style: { fill: #F6F9FE, stroke: #CED4DA } }, defaultEdge: { type: cubic-horizontal, style: { stroke: #ADB5BD, lineWidth: 2 } }, layout: { type: dendrogram, direction: TB, nodeSep: 50, rankSep: 100 } }) }3.2 自定义节点渲染实现带折叠控制的自定义节点G6.registerNode(custom-node, { draw(cfg, group) { const rect group.addShape(rect, { attrs: { x: 0, y: 0, width: cfg.size[0], height: cfg.size[1], radius: 4, fill: cfg.style.fill, stroke: cfg.style.stroke } }) // 节点文本 group.addShape(text, { attrs: { text: cfg.label, x: cfg.size[0] / 2, y: cfg.size[1] / 2, textAlign: center, textBaseline: middle, fill: #495057 } }) // 折叠控制按钮 if (cfg.children cfg.children.length 0) { const marker group.addShape(marker, { attrs: { x: cfg.size[0] - 15, y: cfg.size[1] / 2, r: 6, symbol: cfg.collapsed ? this.expandIcon : this.collapseIcon, stroke: #868E96 }, name: collapse-icon }) marker.on(click, evt { evt.stopPropagation() this.toggleCollapse(cfg.id) }) } return rect }, collapseIcon(x, y, r) { return [ [M, x - r, y], [L, x r, y], [M, x, y - r], [L, x, y r] ] }, expandIcon(x, y, r) { return [ [M, x - r, y], [L, x r, y] ] } }, single-shape)4. 高级功能实现4.1 动态折叠展开实现节点状态管理功能methods: { toggleCollapse(nodeId) { const node this.graph.findById(nodeId) const model node.getModel() this.graph.updateItem(node, { collapsed: !model.collapsed }) // 自动调整布局 setTimeout(() { this.graph.layout() this.graph.fitView() }, 100) } }4.2 响应式容器添加窗口大小变化的响应处理mounted() { this.initGraph() window.addEventListener(resize, this.handleResize) }, beforeDestroy() { window.removeEventListener(resize, this.handleResize) }, methods: { handleResize() { if (this.graph) { this.graph.changeSize( this.$el.clientWidth, this.containerHeight ) this.graph.fitView() } } }4.3 性能优化策略针对大型树结构的优化方案initGraph() { this.graph new TreeGraph({ // ...其他配置 renderer: svg, // 使用SVG渲染器 animate: false, // 关闭动画 groupByTypes: false }) // 启用虚拟渲染 this.graph.get(canvas).set(localRefresh, false) }5. 企业级应用实践5.1 复杂节点样式设计实现带状态标识的业务节点G6.registerNode(biz-node, { draw(cfg, group) { const baseRect group.addShape(rect, { attrs: { x: 0, y: 0, width: 160, height: 60, radius: 4, fill: this.getStatusColor(cfg.status), stroke: #DEE2E6 } }) // 状态标识 group.addShape(rect, { attrs: { x: 0, y: 0, width: 4, height: 60, fill: this.getStatusAccent(cfg.status) } }) // 主文本 group.addShape(text, { attrs: { text: cfg.label, x: 10, y: 20, textAlign: left, fill: #343A40, fontSize: 14 } }) // 副文本 group.addShape(text, { attrs: { text: cfg.desc || , x: 10, y: 40, textAlign: left, fill: #868E96, fontSize: 12 } }) }, getStatusColor(status) { const map { normal: #E6F7FF, warning: #FFF7E6, error: #FFF1F0 } return map[status] || #F8F9FA } })5.2 与Vue状态管理集成结合Vuex实现状态同步computed: { processedData() { return this.normalizeTreeData(this.$store.state.treeData) } }, watch: { processedData: { handler(newVal) { if (this.graph) { this.graph.changeData(newVal) } }, deep: true } }在项目实际落地过程中我们发现树形结构的性能瓶颈主要出现在节点数量超过500时。通过实现动态加载子节点的策略可以有效解决大规模数据渲染问题。具体实现时可以监听节点展开事件动态请求子节点数据并更新图形。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2431925.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!