vue组件中,使用echarts树图点击节点加载数据,同步折叠展开(包含axios交互)详细教程。

  • Post author:
  • Post category:vue




使用的是echarts@5.3.3版本。4.x.x版本应该是不能控制collapsed是否折叠属性,打印没有collapsed属性。

效果图:

在这里插入图片描述


父组件 – 传给子组件根数据

this.$refs.relatedModel_gx.initListParms(this.model)


子节组件 – row来接收传参

    initListParms (row) { // row是父子间传来的根节点数据
      console.log(row);
      this.fadRow = row
      this.datas = [] // 初始化根节点
      this.datas.push({//把父组件数据添加进根节点
        name: row.idxname,
        value: row.idxcode,
        idxrels: row.idxrels,
        children: [],
        collapsed: true //默认根节点闭合,这里是用来判断请求数据的条件

      })
    },


初始化一个echarts,用来渲染根节点

 drewTree (data) {
      this.myChart = echarts.init(document.getElementById('main')) // 把echarts实例放到data中,方便操作
      this.myChart.setOption({
        tooltip: {
          trigger: 'item',
          triggerOn: 'mousemove',
          formatter: function (params) {
            console.log(params);
            return "测点名:" + params.data.name + '<br/>' +
              "测点标签:" + params.data.value + '<br/>' +
              "关联测点:" + params.data.idxrels
          }
        },
        series: [
          {
            type: 'tree',
            data: data,
            top: '1%',
            left: '7%',
            bottom: '1%',
            right: '20%',
            symbol: 'emptyCircle',
            orient: 'horizontal',
            symbol: function (params, params1) {
              if (params !== undefined) {
                console.log(params, params1.collapsed)
                if (params.indexOf('cal_') !== -1) { //指标
                  params1.data.label = {
                    color: '#0099cc',
                    borderWidth: '2', // 边框宽度
                    fontSize: '13',
                  }
                } else if (params.indexOf('lr_') !== -1) { // 录入
                  params1.data.label = {
                    color: '#286355',
                    borderWidth: '2', // 边框宽度
                    fontSize: '13',
                  }
                } else {
                  params1.data.label = {
                    color: '#e06c75',
                    borderWidth: '2', // 边框宽度
                    fontSize: '13',
                  }
                }
              }

            },
            expandAndCollapse: true,
            initialTreeDepth: 0,
            label: {
              position: 'top',
              // rotate: -90,
              verticalAlign: 'middle',
              align: 'right',
              fontSize: 12,
              formatter: function (params) {
                console.log(params);
                return params.data.name + '\n' +
                  params.data.value
              }
            },
            leaves: {
              label: {
                position: 'bottom',
                // rotate: -90,
                verticalAlign: 'middle',
                align: 'left'
              }
            },
            animationDurationUpdate: 750
          }
        ]

      })
      this.myChart.on('click', this.getGlTag)
    },


给树图节点添加点击事件

 this.myChart.on('click', this.getGlTag)


点击事件中请求数据,注意异步请求造成向数组添加数据的失败,导致最后形成空数组,拿不到数据。可以使用定时器。

    yibu (idxrels) { // 在这里发送请求
      return new Promise((resolve, reject) => { 
        var data = []
        idxrels.map(item => {  
          if (item.indexOf('cal_') == -1) { // 这里判断使用那个接口
            this.axios.get(`/xxxxxxxx/list?ptkks=${item}`) // 获取测点关联
              .then((res) => {
                if (res.success) {
                  // console.log(res.result.records[0]);
                  let cditem = res.result.records[0]
                  let obj = {
                    name: cditem.ptdescript,
                    value: cditem.ptkks,
                    idxrels: [],
                    children: [],
                    collapsed: true//添加的子节点默认是闭合的,之后单击可以请求数据(不然就得点两下)

                  }
                  console.log(obj);
                  console.log(data);
                  if (res.result.records[0] !== undefined) {
                    data.push(obj)
                  }
                } else {
                  this.$message.error(res.message)
                }

              })
          } else if (item.indexOf('cal_') !== -1) {
            this.axios.get(`/xxxxx/list?idxcode=${item}`)// 获取指标关联
              .then((res) => {
                if (res.success) {
                  let zbitem = res.result.records[0]
                  let obj = {
                    name: zbitem.idxname,
                    value: zbitem.idxcode,
                    idxrels: zbitem.idxrels,
                    children: [],
                    collapsed: true,//添加的子节点默认是闭合的,之后单击可以请求数据(不然就得点两下)
                  }
                  if (res.result.records !== []) {
                    data.push(obj)
                    console.log(obj);
                  }
                } else {
                  this.$message.error(res.message)
                }
              })
          }
        })
        setTimeout(() => {
          resolve(data)
        }, 600)
      })

    },
 async getGlTag (param) { // 请求关联点,不知道是async await 生效,还是定时器生效,我觉得是定时器,解决数据push完还是空数组的异步问题

      console.log(param);
      if (param.data.idxrels.length !== 0) {
        console.log('进');
        var newIdxrels = param.data.idxrels.split(",") //处理 请求子节点数据时 要用的参数。
        this.getChildData = await this.yibu(newIdxrels) // 请求回来的子节点数据
        console.log(this.getChildData, '请求回来的子节点数据');
        this.clickFun(param) // 准备讲子节点数据渲染到echarts
      } else {
        this.$message.warning('暂无关联点!')
      }
    },


最后把数据渲染到echarts上

 clickFun (param) {
      if (typeof param.seriesIndex == 'undefined') {
        return;
      }
      if (param.type == 'click') {
        if (param.data.collapsed == false) { //collapsed = false 代表打开状态
          console.log('关了');
          param.data.collapsed = true // 我们就闭合节点
          param.data.children = [] // 清除节点数据
          return
        } else if ((param.data.collapsed == true)) {//collapsed = true 代表折叠状态
          console.log('开了');
          param.data.collapsed = false // 我们把它展开
          param.data.children = [] // 先初始化节点数据
          console.log(this.getChildData, '我们请求回来的子节点数据=>数组');
          this.getChildData.map(item => { // 循环添加到子节点中
            param.data.children.push(item)
          })

          this.getChildData = [] // 添加完后清空容器,之后请求的节点数据还会保存在 this.getChildData 中
          console.log(param.data.children);
          if (param.data.children.length > 0) {
            console.log('有数据,会渲染')
            console.log(this.myChart.getOption().series[0].data);
            let data = this.myChart.getOption().series[0].data;
            this.myChart.clear();
            this.myChart.setOption(
              {
                tooltip: {
                  trigger: 'item',
                  triggerOn: 'mousemove',
                  formatter: function (params) {
                    // console.log(params);
                    return "测点名:" + params.data.name + '<br/>' +
                      "测点标签:" + params.data.value + '<br/>' +
                      "关联测点:" + params.data.idxrels
                  }
                },

                series: [
                  {
                    type: 'tree',
                    data: data,
                    top: '1%',
                    left: '7%',
                    bottom: '1%',
                    right: '20%',
                    symbol: 'emptyCircle',
                    itemStyle: {
                      normal: {
                        color: '#b22125'
                      },
                      emphasis: {
                        borderColor: '#ccc'
                      }
                    },
                    symbol: function (params, params1) { // 自定义label颜色
                      if (params !== undefined) {
                        console.log(params, params1.collapsed)
                        if (params.indexOf('cal_') !== -1) { //指标
                          params1.data.label = {
                            color: '#0099cc',
                            borderWidth: '2', // 边框宽度
                            fontSize: '13',
                          }
                        } else if (params.indexOf('lr_') !== -1) { // 录入
                          params1.data.label = {
                            color: '#286355',
                            borderWidth: '2', // 边框宽度
                            fontSize: '13',
                          }
                        } else {
                          params1.data.label = {
                            color: '#e06c75',
                            borderWidth: '2', // 边框宽度
                            fontSize: '13',
                          }
                        }
                      }
                    },
                    orient: 'horizontal',
                    expandAndCollapse: true, //初始根节点是闭合状态,我们才能点击请求子节点
                    label: {
                      position: 'top',
                      // rotate: -90, // 旋转label
                      verticalAlign: 'middle',
                      align: 'right',
                      fontSize: 12,
                      formatter: function (params) {
                        return params.data.name + '\n' +
                          params.data.value
                      }
                    },
                    leaves: {
                      label: {
                        position: 'bottom',
                        // rotate: -90,
                        verticalAlign: 'middle',
                        align: 'left'
                      }
                    },
                    animationDurationUpdate: 750
                  }
                ]
              });
          } else {
            console.log('暂无数据');
          }
        }
      }
    }


完整代码 – 子组件中的echarts

<template>
  <div class="dashboard-container">
    <div id="main"
         ref="main"
         style="width:100%;height: 700px;padding:30px" />
  </div>
</template>
<script>
const echarts = require('echarts')
import { EleResize } from './echartsResize.js'
export default {
  name: 'Dashboard',
  props: {
  },
  data () {
    return {
      myChart: null, // echarts初始化
      datas: [],  //根接点数据 - 处理过的
      fadRow: {}, //父组件传来的根节点数据 - 未经处理
      getChildData: [], //保存每个子节点数据,用完后即使初始化。
    }
  },
  mounted () {
  },
  watch: {
    datas: { // 监听根节点的变化,一旦变化,立刻重新渲染根节点。
      handler: function (newVal, oldVal) {
        console.log('调用初始化ect');
        this.drewTree(newVal)
      },
      deep: true
    }
  },
  methods: {
    drewTree (data) {
      this.myChart = echarts.init(document.getElementById('main'))
      this.myChart.setOption({
        tooltip: {
          trigger: 'item',
          triggerOn: 'mousemove',
          formatter: function (params) {
            console.log(params);
            return "测点名:" + params.data.name + '<br/>' +
              "测点标签:" + params.data.value + '<br/>' +
              "关联测点:" + params.data.idxrels
          }
        },
        series: [
          {
            type: 'tree',
            data: data,
            top: '1%',
            left: '7%',
            bottom: '1%',
            right: '20%',
            symbol: 'emptyCircle',
            orient: 'horizontal',
            symbol: function (params, params1) { //根据不同的属性,控制颜色
              if (params !== undefined) {
                console.log(params, params1.collapsed)
                if (params.indexOf('cal_') !== -1) { //指标
                  params1.data.label = {
                    color: '#0099cc',
                    borderWidth: '2', // 边框宽度
                    fontSize: '13',
                  }
                } else if (params.indexOf('lr_') !== -1) { // 录入
                  params1.data.label = {
                    color: '#286355',
                    borderWidth: '2', // 边框宽度
                    fontSize: '13',
                  }
                } else {
                  params1.data.label = {
                    color: '#e06c75',
                    borderWidth: '2', // 边框宽度
                    fontSize: '13',
                  }
                }
              }

            },
            expandAndCollapse: true,
            initialTreeDepth: 0,
            label: {
              position: 'top',
              // rotate: -90,
              verticalAlign: 'middle',
              align: 'right',
              fontSize: 12,
              formatter: function (params) {
                console.log(params);
                return params.data.name + '\n' +
                  params.data.value
              }
            },
            leaves: {
              label: {
                position: 'bottom',
                // rotate: -90,
                verticalAlign: 'middle',
                align: 'left'
              }
            },
            animationDurationUpdate: 750
          }
        ]

      })
      this.myChart.on('click', this.getGlTag)
    },
    initListParms (row) { // 获取根节点数据
      console.log(row);
      this.fadRow = row
      this.datas = [] // 初始化根节点
      this.datas.push({
        name: row.idxname,
        value: row.idxcode,
        idxrels: row.idxrels,
        children: [],
        collapsed: true //默认根节点闭合,这里是用来判断请求数据的条件

      })
    },
      yibu (idxrels) {
      return new Promise((resolve, reject) => {
        var data = []
        idxrels.map(item => {
          if (item.indexOf('cal_') == -1) {
            this.axios.get(`/xxxxxxxx/list?ptkks=${item}`) // 获取测点关联
              .then((res) => {
                if (res.success) {
                  let cditem = res.result.records[0]
                  let obj = {
                    name: cditem.ptdescript,
                    value: cditem.ptkks,
                    idxrels: [],
                    children: [],
                    collapsed: true//添加的子节点默认是闭合的,之后单击可以请求数据(不然就得点两下)

                  }
                  console.log(obj);
                  console.log(data);
                  if (res.result.records[0] !== undefined) {
                    data.push(obj)
                  }
                } else {
                  this.$message.error(res.message)
                }

              })
          } else if (item.indexOf('cal_') !== -1) {
            this.axios.get(`/xxxxxxxx/list?idxcode=${item}`)// 获取指标关联
              .then((res) => {
                if (res.success) {
                  let zbitem = res.result.records[0]
                  let obj = {
                    name: zbitem.idxname,
                    value: zbitem.idxcode,
                    idxrels: zbitem.idxrels,
                    children: [],
                    collapsed: true,//添加的子节点默认是闭合的,之后单击可以请求数据(不然就得点两下)
                  }
                  if (res.result.records !== []) {
                    data.push(obj)
                    console.log(obj);
                  }
                } else {
                  this.$message.error(res.message)
                }
              })
          }
        })
        setTimeout(() => {
          resolve(data)
        }, 600)
      })

    },
    //点击节点后,先请求子节点数据
    async getGlTag (param) { // 请求关联点
      console.log(param);
      if (param.data.idxrels.length !== 0) { // 如果含有请求参数,说明有子节点,这里没有haschild标识,有请求参数就可以判断还可以展开有子节点。
        var newIdxrels = param.data.idxrels.split(",")
        this.getChildData = await this.yibu(newIdxrels)
        console.log(this.getChildData, '555');
        this.clickFun(param)
      } else {
        this.$message.warning('暂无关联点!')
      }
    },
    clickFun (param) {
      if (typeof param.seriesIndex == 'undefined') {
        return;
      }
      console.log(param.collapsed, this.getChildData, '开关标识');
      if (param.type == 'click') {
       // 通过打印,发现没有展开的节点,和最后一层子节点的collapsed属性都为true
       // 所以判断collapsed为true,并且没有孩子节点的时候,就是还有没展开的子节点
        if (param.data.collapsed == false) {
          console.log('关了');
          param.data.collapsed = true
          param.data.children = []
          return
        } else if ((param.data.collapsed == true)) {
          console.log('开了');
          console.log(this.getChildData);
          // param.collapsed = true
          param.data.collapsed = false
          param.data.children = []
          console.log(this.getChildData, ' this.getChildData');
          this.getChildData.map(item => {
            console.log('item');
            param.data.children.push(item)
          })

          this.getChildData = []
          console.log(param.data.children);

          if (param.data.children.length > 0) {
            console.log('有数据')
            console.log(this.myChart.getOption().series[0].data);
            let data = this.myChart.getOption().series[0].data;
            this.myChart.clear();
            this.myChart.setOption(
              {
                tooltip: {
                  trigger: 'item',
                  triggerOn: 'mousemove',
                  formatter: function (params) {
                    // console.log(params);
                    return "测点名:" + params.data.name + '<br/>' +
                      "测点标签:" + params.data.value + '<br/>' +
                      "关联测点:" + params.data.idxrels
                  }
                },

                series: [
                  {
                    type: 'tree',
                    data: data,
                    top: '1%',
                    left: '7%',
                    bottom: '1%',
                    right: '20%',
                    symbol: 'emptyCircle',
                    // symbol: 'emptyCircle',
                    // symbol: {
                    //   formatter: function (params) {
                    //    console.log(params);
                    //   }
                    // },
                    // symbol: function (params) {
                    //   console.log(params);
                    //   let icon = params.data.idxrels.length > 0 ? 'emptyCircle' : 'circle'
                    //   return icon
                    // },
                    itemStyle: {
                      normal: {
                        color: '#b22125'
                      },
                      emphasis: {
                        borderColor: '#ccc'
                      }
                    },
                    symbol: function (params, params1) {
                      // 修改label的样式,来判断是否还存在子节点没展开
                      if (params !== undefined) {
                        console.log(params, params1.collapsed)
                        if (params.indexOf('cal_') !== -1) { //指标
                          params1.data.label = {
                            color: '#0099cc',
                            borderWidth: '2', // 边框宽度
                            fontSize: '13',
                          }
                        } else if (params.indexOf('lr_') !== -1) { // 录入
                          params1.data.label = {
                            color: '#286355',
                            borderWidth: '2', // 边框宽度
                            fontSize: '13',
                          }
                        } else {
                          params1.data.label = {
                            color: '#e06c75',
                            borderWidth: '2', // 边框宽度
                            fontSize: '13',
                          }
                        }
                      }

                    },
                    orient: 'horizontal',
                    expandAndCollapse: true,
                    label: {
                      position: 'top',
                      // rotate: -90,
                      verticalAlign: 'middle',
                      align: 'right',
                      fontSize: 12,
                      formatter: function (params) {
                        return params.data.name + '\n' +
                          params.data.value
                      }
                    },
                    leaves: {
                      label: {
                        position: 'bottom',
                        // rotate: -90,
                        verticalAlign: 'middle',
                        align: 'left'
                      }
                    },
                    animationDurationUpdate: 750
                  }
                ]
              });
          } else {
            console.log('暂无数据');
          }
        }
      }
    }
  },

}

</script>

<style lang='less' scoped>
.dashboard {
  &-container {
    margin: 30px;
  }
  &-text {
    font-size: 30px;
    line-height: 46px;
  }
}
</style>


代码仍有优化余地



版权声明:本文为weixin_45930242原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。