使用 Vue+axios+Echarts 绘制关系图遇到的坑

本贴最后更新于 1666 天前,其中的信息可能已经时过境迁

最近做毕设,后端采用的是 Spring boot,通过 Neo4jRepository 从 neo4j 中获取数据,前端框架是 Vue,通过 axios 请求后端数据,并处理成符合 Echarts 规范的数据格式,之后 Echarts 进行渲染。在前端渲染数据的过程中遇到好多坑。

首先是如何对后端返回的数据进行处理。后端返回的数据格式是这样的:

[
  {
    "id": 1,
    "name": "CSS"
  },
  {
    "id": 2,
    "name": "Javascript",
    "derives": [
      {
        "id": 3,
        "name": "Vue.js"
      }
    ]
  },
  {
    "id": 3,
    "name": "Vue.js"
  },
  {
    "id": 171,
    "name": "前端技术",
    "includes": [
      {
        "id": 1,
        "name": "CSS"
      },
      {
        "id": 2,
        "name": "Javascript",
        "derives": [
          {
            "id": 3,
            "name": "Vue.js"
          }
        ]
      },
      {
        "id": 172,
        "name": "HTML",
      }
    ]
  },
  {
    "id": 172,
    "name": "HTML",
  }
]

对应的 Echarts 规范数据应当是:

data:[
  {
    name: "CSS"
  },
  {
    name: "Javascript"
  },
  {
    name: "Vue.js"
  },
  {
    name: "前端技术"
  },
  {
    name: "HTML"
  }
],
links: [
  {
    source: "Javascript",
    target: "Vue.js",
    name: "衍生出"
  },
  {
    source: "前端技术",
    target: "HTML",
    name: "包含"
  },
  {
    source: "前端技术",
    target: "CSS",
    name: "包含"
  },
  {
    source: "前端技术",
    target: "Javascript",
    name: "包含"
  }
]

遇到的坑主要是两个。第一个是处理返回的数据,返回数据存在对象 resData 中,我建立了两个空白数组 graphData 和 graphLinkes 用于存储包装好的数据,然后使用 for 循环处理 resData,正确的代码如下:

for(var i=0,len=response.data.length;i<len;i++){
    me.graphData.push({
        name: me.resData[i].name,
        des: 'nodedes05',
        symbolSize: 50,
        category: 1,
    });
    if("includes" in me.resData[i]){
        let dataIncludes=me.resData[i].includes;
        for(var j=0,lenj=dataIncludes.length;j<lenj;j++){
            me.graphLinks.push({
                source: me.resData[i].name,
                target: dataIncludes[j].name,
                name: '包含',
                des: j
            })
        }
    } 
    if("derives" in me.resData[i]){   
        let dataDerives=me.resData[i].derives;
        for(var j=0,lenj=dataDerives.length;j<lenj;j++){
            me.graphLinks.push({
                source: me.resData[i].name,
                target: dataDerives[j].name,
                name: '衍生出',
                des: j
            })
        }
    }        
}

但是一开始我想用 for in 循环却一直失败,不知道怎么回事。最后只能用最传统的 i++。

第二个坑在 Echarts 渲染上。从后台获取数据的和渲染图形分别写在两个方法中,方法名为 loadData 和 drawline。一开始我是在 mounted 中先执行 loadData,再执行 drawline。但这样不能用。后来去网上搜了一下说是在获取到数据后立马执行 drawline 才行,不过网上也没有说为什么。我想了一下这应该是异步执行的问题。如果因为在 loadData 中使用的 axios 是异步方法,也就是不需要完全执行完里面的语句就可以继续执行后面的方法。因此在我们调用 drawline 的时候数据根本还没有从后台接口获取到。而如果在获取数据后立马执行,更确切的说是在 axios then 方法体内立马执行,而在 axios 方法内部的语句还是同步执行的,这就保证了我们已经从后台接口获取到了数据,之后渲染就没问题了。

完整代码如下:

<template>
   
<div id="myChart"></div>
</template>

<style>
    #myChart{
        width: 100%;
        height: 1000px;
    }
</style>
<script>
export default {
    name:"Graph",
    data () {
    return {
      msg: 'Welcome to Your Vue.js App',
      categories: [],
      resData: [],
      graphData: [],
      graphLinks: []
    }
  },
  mounted(){
    for (var i = 0; i < 2; i++) {
        this.categories[i] = {
            name: '类目' + i
        };
    }
    this.loadData();
    //this.drawLine();
  },
  methods: {
    drawLine(){
        // 基于准备好的dom,初始化echarts实例
        let myChart = this.$echarts.init(document.getElementById('myChart'));
        // 绘制图表
        myChart.setOption({
            title: {
              text: 'ECharts 关系图'
            },
            tooltip: {},
            
            series: [{
              type: 'graph', // 类型:关系图
                layout: 'force', //图的布局,类型为力导图
                symbolSize: 40, // 调整节点的大小
                roam: true, // 是否开启鼠标缩放和平移漫游。默认不开启。如果只想要开启缩放或者平移,可以设置成 'scale' 或者 'move'。设置成 true 为都开启
                edgeSymbol: ['circle', 'arrow'],
                edgeSymbolSize: [2, 10],
                edgeLabel: {
                    normal: {
                        textStyle: {
                            fontSize: 20
                        }
                    }
                },
                force: {
                    repulsion: 2500,
                    edgeLength: [10, 50]
                },
                draggable: true,
                lineStyle: {
                    normal: {
                        width: 2,
                        color: '#4b565b',
                    }
                },
                edgeLabel: {
                    normal: {
                        show: true,
                        formatter: function (x) {
                            return x.data.name;
                        }
                    }
                },
                label: {
                    normal: {
                        show: true,
                        textStyle: {}
                    }
                },
                data: this.graphData,
                links: this.graphLinks,
                categories: this.categories,
            }]
        });
    },
    loadData(){
        let me=this;
        axios.get('http://localhost:8080/graph/all')
        .then(function (response){
            me.resData=response.data;
            for(var i=0,len=response.data.length;i<len;i++){
                me.graphData.push({
                    name: me.resData[i].name,
                    des: 'nodedes05',
                    symbolSize: 50,
                    category: 1,
                });
                if("includes" in me.resData[i]){
                    let dataIncludes=me.resData[i].includes;
                    for(var j=0,lenj=dataIncludes.length;j<lenj;j++){
                        me.graphLinks.push({
                            source: me.resData[i].name,
                            target: dataIncludes[j].name,
                            name: '包含',
                            des: j
                        })
                    }
                } 
                if("derives" in me.resData[i]){   
                    let dataDerives=me.resData[i].derives;
                    for(var j=0,lenj=dataDerives.length;j<lenj;j++){
                        me.graphLinks.push({
                            source: me.resData[i].name,
                            target: dataDerives[j].name,
                            name: '衍生出',
                            des: j
                        })
                    }
                }        
            }
            me.drawLine();
        })
        .catch(function (error) {
            console.log(error);
        });
    }
  }
}
</script>

  • axios
    7 引用 • 5 回帖
  • ECharts
    19 引用 • 20 回帖
  • Vue.js

    Vue.js(读音 /vju ː/,类似于 view)是一个构建数据驱动的 Web 界面库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

    264 引用 • 665 回帖
  • 异步
    10 引用 • 51 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • GitLab

    GitLab 是利用 Ruby 一个开源的版本管理系统,实现一个自托管的 Git 项目仓库,可通过 Web 界面操作公开或私有项目。

    46 引用 • 72 回帖 • 1 关注
  • Windows

    Microsoft Windows 是美国微软公司研发的一套操作系统,它问世于 1985 年,起初仅仅是 Microsoft-DOS 模拟环境,后续的系统版本由于微软不断的更新升级,不但易用,也慢慢的成为家家户户人们最喜爱的操作系统。

    221 引用 • 473 回帖
  • IPFS

    IPFS(InterPlanetary File System,星际文件系统)是永久的、去中心化保存和共享文件的方法,这是一种内容可寻址、版本化、点对点超媒体的分布式协议。请浏览 IPFS 入门笔记了解更多细节。

    21 引用 • 245 回帖 • 248 关注
  • gRpc
    11 引用 • 9 回帖 • 60 关注
  • FFmpeg

    FFmpeg 是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。

    23 引用 • 32 回帖 • 2 关注
  • Vditor

    Vditor 是一款浏览器端的 Markdown 编辑器,支持所见即所得、即时渲染(类似 Typora)和分屏预览模式。它使用 TypeScript 实现,支持原生 JavaScript、Vue、React 和 Angular。

    346 引用 • 1801 回帖 • 3 关注
  • 服务

    提供一个服务绝不仅仅是简单的把硬件和软件累加在一起,它包括了服务的可靠性、服务的标准化、以及对服务的监控、维护、技术支持等。

    41 引用 • 24 回帖
  • Laravel

    Laravel 是一套简洁、优雅的 PHP Web 开发框架。它采用 MVC 设计,是一款崇尚开发效率的全栈框架。

    20 引用 • 23 回帖 • 725 关注
  • Wide

    Wide 是一款基于 Web 的 Go 语言 IDE。通过浏览器就可以进行 Go 开发,并有代码自动完成、查看表达式、编译反馈、Lint、实时结果输出等功能。

    欢迎访问我们运维的实例: https://wide.b3log.org

    30 引用 • 218 回帖 • 625 关注
  • HHKB

    HHKB 是富士通的 Happy Hacking 系列电容键盘。电容键盘即无接点静电电容式键盘(Capacitive Keyboard)。

    5 引用 • 74 回帖 • 465 关注
  • 百度

    百度(Nasdaq:BIDU)是全球最大的中文搜索引擎、最大的中文网站。2000 年 1 月由李彦宏创立于北京中关村,致力于向人们提供“简单,可依赖”的信息获取方式。“百度”二字源于中国宋朝词人辛弃疾的《青玉案·元夕》词句“众里寻他千百度”,象征着百度对中文信息检索技术的执著追求。

    63 引用 • 785 回帖 • 181 关注
  • 大疆创新

    深圳市大疆创新科技有限公司(DJI-Innovations,简称 DJI),成立于 2006 年,是全球领先的无人飞行器控制系统及无人机解决方案的研发和生产商,客户遍布全球 100 多个国家。通过持续的创新,大疆致力于为无人机工业、行业用户以及专业航拍应用提供性能最强、体验最佳的革命性智能飞控产品和解决方案。

    2 引用 • 14 回帖
  • CentOS

    CentOS(Community Enterprise Operating System)是 Linux 发行版之一,它是来自于 Red Hat Enterprise Linux 依照开放源代码规定释出的源代码所编译而成。由于出自同样的源代码,因此有些要求高度稳定的服务器以 CentOS 替代商业版的 Red Hat Enterprise Linux 使用。两者的不同在于 CentOS 并不包含封闭源代码软件。

    238 引用 • 224 回帖 • 1 关注
  • 开源中国

    开源中国是目前中国最大的开源技术社区。传播开源的理念,推广开源项目,为 IT 开发者提供了一个发现、使用、并交流开源技术的平台。目前开源中国社区已收录超过两万款开源软件。

    7 引用 • 86 回帖
  • 工具

    子曰:“工欲善其事,必先利其器。”

    285 引用 • 728 回帖
  • BAE

    百度应用引擎(Baidu App Engine)提供了 PHP、Java、Python 的执行环境,以及云存储、消息服务、云数据库等全面的云服务。它可以让开发者实现自动地部署和管理应用,并且提供动态扩容和负载均衡的运行环境,让开发者不用考虑高成本的运维工作,只需专注于业务逻辑,大大降低了开发者学习和迁移的成本。

    19 引用 • 75 回帖 • 632 关注
  • 友情链接

    确认过眼神后的灵魂连接,站在链在!

    24 引用 • 373 回帖
  • Android

    Android 是一种以 Linux 为基础的开放源码操作系统,主要使用于便携设备。2005 年由 Google 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

    334 引用 • 323 回帖
  • CAP

    CAP 指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得。

    11 引用 • 5 回帖 • 606 关注
  • Quicker

    Quicker 您的指尖工具箱!操作更少,收获更多!

    30 引用 • 123 回帖 • 1 关注
  • JRebel

    JRebel 是一款 Java 虚拟机插件,它使得 Java 程序员能在不进行重部署的情况下,即时看到代码的改变对一个应用程序带来的影响。

    26 引用 • 78 回帖 • 657 关注
  • Webswing

    Webswing 是一个能将任何 Swing 应用通过纯 HTML5 运行在浏览器中的 Web 服务器,详细介绍请看 将 Java Swing 应用变成 Web 应用

    1 引用 • 15 回帖 • 619 关注
  • 禅道

    禅道是一款国产的开源项目管理软件,她的核心管理思想基于敏捷方法 scrum,内置了产品管理和项目管理,同时又根据国内研发现状补充了测试管理、计划管理、发布管理、文档管理、事务管理等功能,在一个软件中就可以将软件研发中的需求、任务、bug、用例、计划、发布等要素有序的跟踪管理起来,完整地覆盖了项目管理的核心流程。

    6 引用 • 15 回帖 • 127 关注
  • 钉钉

    钉钉,专为中国企业打造的免费沟通协同多端平台, 阿里巴巴出品。

    15 引用 • 67 回帖 • 338 关注
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 1 关注
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    942 引用 • 1459 回帖 • 31 关注
  • webpack

    webpack 是一个用于前端开发的模块加载器和打包工具,它能把各种资源,例如 JS、CSS(less/sass)、图片等都作为模块来使用和处理。

    41 引用 • 130 回帖 • 257 关注