el-table中显示echarts的趋势折线图(燃尽图)

本文档详细介绍了如何使用Vue.js来模仿禅道上的燃尽图,重点在于解决数据不唯一和ECharts图表绘制的问题。首先通过el-table渲染表格,然后利用Promise确保异步操作的顺序,动态生成ECharts图表容器并绑定数据,最后通过myChart.setOption()绘制折线图,并实现窗口自适应。关键点包括DOM渲染、数据绑定和ECharts初始化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

显示效果:右边的趋势图其实是查询当前行的30天数据量

 背景:为了模仿禅道上的燃尽图,但是查看其源码,发现是用php写的,我们想用vue实现

 实现步骤:1.先使用el-table画出表格来 

注意:此时数据是放在list中的,但是趋势图中的id又不能唯一,又需要根据id获取该dev改成echarts的折线图,所以使用d="'main_'+scope.row.rank"来替换。后面的style可以控制该趋势图的大小

<el-table
      :data="list"
      :height='570'
      @selection-change="setSelectRows"
    >
      <el-table-column prop="rank" label="排名" :style="{margin,left: '50px'}" show-overflow-tooltip ></el-table-column>
      <el-table-column prop="name" label="名称" show-overflow-tooltip ></el-table-column>
      <el-table-column prop="city" label="所属市" show-overflow-tooltip ></el-table-column>
      <el-table-column prop="province" label="所属省" show-overflow-tooltip ></el-table-column>
      <el-table-column prop="num" label="数量" show-overflow-tooltip ></el-table-column>
      <el-table-column label="趋势图" show-overflow-tooltip>
        <template #default="scope">
            <!--为echarts准备一个具备大小的容器dom-->
          <div :id="'main_'+scope.row.rank" style="width:70%;height:30px;margin: 0 auto;"></div>
        </template>
      </el-table-column>

2.趋势图中的数据赋值:后台获取数

注意:1 此处的精华在于initEcharts方法中的 Promise.then():Promise .then的用意就是使异步代码的执行过程可以按照指定的顺序从上到下依次执行,打破了异步代码的局限性。trendQuery方法是个异步方法,没有initEcharts方法,直接调用initData的同步方法,则会出现div还没渲染就要调用id,则会出现调用不到的报错:Uncaught Error: Initialize failed: invalid dom-------这是由于echarts在初始化化时是需要获取dom 2. 通过"main_" + state.list[i].rank) 来和上述html中的id对应获取对应行的字段

import * as echarts from 'echarts'



const fetchData = async () => {
      state.listLoading = true
      const {
        retCode, success, data, msg
      } = await trendQuery(state.queryForm)
      if (retCode == 0) {
        state.list = data.records;

        initEcharts();
      } else {
        proxy.$baseMessage(msg, 'error', 'vab-hey-message-error');
      }
    }

// 方法
const initEcharts = () => {
      // 新建一个promise对象
      let newPromise = new Promise((resolve) => {
        resolve()
      })
      //然后异步执行echarts的初始化函数
      newPromise.then(() => {
        //	此dom为echarts图标展示dom
        // echarts.init(DOm)
        initData();
      })
    }

const initData = () => {
      console.log(" initData 执行中 ")
      for (let i = 0; i < state.list.length; i++) {
        let myChart = echarts.init(document.getElementById("main_" + state.list[i].rank));
        // 绘制图表
        myChart.setOption({
          xAxis: {
            show: false, //取消显示坐标轴,坐标轴刻度,坐标值(如果是y轴,默认的网格线也会取消显示)
            type: 'category',
            boundaryGap: false,
            splitLine: {
              show:false
            },
            data: []
          },
          grid: {
            left: "0",
            top: "0",
            right: "0",
            bottom: "0",
            containLabel: true,
          },
          yAxis: {
            axisLabel: { // 取消显示坐标值
              show: false
            },
            splitLine: { //取消网格线
              show:false
            },
            type: 'value'
          },
          series: [
            {
              symbol: "none",
              smooth: true,//平滑
              type: "line",
              data: state.list[i].trend,
              areaStyle: {}
            }
          ]
        });
        window.onresize = function () { // 自适应大小
          myChart.resize();
        };
      }
    }

 3.绘制图像

使用的是 myChart.setOption({ ......}) ,有兴趣的可以在echarts官网的案例中查看Documentation - Apache ECharts和练习

Examples - Apache ECharts

### 问题分析 当 `el-table-column` 设置了 `fixed` 属性后,表格会生成两份 DOM 结构:一份用于滚动部分,另一份用于固定列。这种机制可能导致某些依赖于唯一 DOM 节点的功能出现问题,比如 `el-popover` 中嵌套的 ECharts 表可能因为重复渲染而无法正常显示。 以下是针对此问题的具体解决方案: --- ### 方案一:动态调整 Popover 的触发器位置 通过为每个 `el-popover` 动态分配唯一的 `ref`,并手动控制其打开和关闭状态,可以有效避免因多层 DOM 复制而导致的问题。 #### 实现方式 1. **绑定动态 ref** 在模板中为每个 `el-popover` 添加基于数据 ID 或索引的动态 `ref`。 ```vue <el-table-column prop="chart" label="ECharts"> <template slot-scope="scope"> <el-popover :ref="'popover_' + scope.$index" trigger="manual" v-model="visible[scope.$index]" > <div id="chartContainer" style="width: 300px; height: 200px;"></div> <span slot="reference" @click="handleClick(scope.$index)" >查看表</span> </el-popover> </template> </el-table-column> ``` 2. **初始化 ECharts** 在 Vue 生命周期钩子函数中初始化 ECharts 并将其挂载到对应的容器上。 ```javascript export default { data() { return { visible: [], // 控制 popover 显示状态 }; }, methods: { handleClick(index) { this.visible[index] = true; this.initChart('chartContainer'); }, initChart(containerId) { const chartDom = document.getElementById(containerId); if (chartDom) { const myChart = echarts.init(chartDom); // 初始化 ECharts 实例 const option = { /* 配置项 */ }; // 定义表配置 myChart.setOption(option); } }, }, }; ``` 3. **手动管理可见性** 当用户点击外部区域或其他操作时,可以通过编程方式隐藏当前激活的 `el-popover`。 ```javascript closePopover(index) { this.visible[index] = false; } ``` --- ### 方案二:替换为 Dialog 组件 如果上述方法仍无法解决问题,建议改用更稳定的弹窗组件(如 `el-dialog`),以规避因 `fixed` 列引起的复杂 DOM 行为。 #### 实现方式 1. **移除 el-popover** 替代为 `el-dialog`,并将 ECharts 渲染逻辑迁移到对话框内部。 ```vue <el-button type="text" @click="openDialog">查看表</el-button> <el-dialog title="ECharts 表" :visible.sync="dialogVisible"> <div id="dialogChart" style="width: 600px; height: 400px;"></div> </el-dialog> ``` 2. **初始化 ECharts** 同样在 Vue 方法中完成表实例化。 ```javascript export default { data() { return { dialogVisible: false, }; }, methods: { openDialog() { this.dialogVisible = true; this.initChart(); }, initChart() { const chartDom = document.getElementById('dialogChart'); if (chartDom) { const myChart = echarts.init(chartDom); const option = { /* 配置项 */ }; myChart.setOption(option); } }, }, }; ``` --- ### 方案三:修复 Fixed 导致的 DOM 冲突 对于希望保留 `el-popover` 的场景,可通过以下手段优化 DOM 结构冲突问题。 1. **禁用多余副本** 修改 Element UI 源码或自定义样式,阻止 `fixed` 列额外复制 DOM 元素。 2. **延迟加载 ECharts** 确保仅在一个有效的 DOM 上初始化 ECharts,其他副本则忽略处理。 ```javascript mounted() { nextTick(() => { const activePopovers = Array.from(document.querySelectorAll('.el-popover')); activePopovers.forEach((popover) => { if (!popover.querySelector('#chartContainer')) return; this.initChart(popover.id); }); }); } ``` --- ### 总结 以上三种方案分别适用于不同需求和技术背景: - 如果追求简单实现,推荐使用 **方案二** (`el-dialog`)- 若需保持原有交互体验,则优先尝试 **方案一** (动态 ref); - 对于深入定制的需求,可考虑 **方案三** 进行底层优化[^3]。 --- ###
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值