vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > vue echarts动态数据刷新

vue踩坑记录之echarts动态数据刷新问题

作者:翟敏1201

这篇文章主要介绍了vue踩坑记录之echarts动态数据刷新问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

vue echarts动态数据刷新

需求是数据发生变化echarts会立即刷新,我将data设置未动态的

请求数据成功之后,将数据插入到investmentnum里面,但是后来发现数据虽然插入成功,但是echarts图却没有变化,所以我猜想是echarts没有刷新

接下来进行填坑

用watch 监听data的变化,数据发生变化时重新初始化echarts图

watch: {
    //观察data的变化
    investmentnum: {
      handler (newVal, oldVal) {
        if (this.chart) {
          for (let i = 0; i < this.investmentnum.length; i++) {
            if (oldVal[i] != newVal[i]) {
              this.option = {
                //echarts
                tooltip: {
                  trigger: 'item',
                  formatter: '{a} <br/>{b} : {c}'
                },
                legend: {
                  right: 'right',
                  // data: ['金额'],
                  data: [{name:'金额',textStyle:{color:'#4a78e8'}}
                  ]
                },
                xAxis: {
                  type: 'category',
                  name: 'x',
                  splitLine: {show: false},
                  data : this.weektime,
                  //设置坐标轴字体颜色
                  axisLine: {
                    lineStyle: {
                      color: '#4a78e8',
                      width: 1,//这里是为了突出显示加上的
                    }}
                },
                grid: {
                  left: '1%',
                  right: '1%',
                  bottom: '3%',
                  containLabel: true
                },
                yAxis: {
                  type: 'value',
                  name: '   金额 (万元)',
                  splitLine: {
                    lineStyle: {
                      // 使用深浅的间隔色
                      color: ['#60bee9']
                    }
                  },
                  nameTextStyle: {
                    color: ['#4a78e8']
                  },
                  axisLine: {
                    lineStyle: {
                      color: '#4a78e8',
                      width: 1,//这里是为了突出显示加上的
                    }
                  },
                  axisLabel: {
                    color: "#7e8c8d" //刻度线标签颜色
                  },
                  min: 0
                },
                series: [
                  {
                    name: '金额',
                    type: 'line',
                    smooth: true,
                    data: this.investmentnum,
                    itemStyle : {
                      normal : {
                        color:'#4a78e8',
                        lineStyle: {
                          color:'#4a78e8'
                        },
                        label: {
                          show: true
                        }
                      }
                    }
                  }
                ]
              }
              this.chart.setOption(this.option)
            }
          }
        } else {
          this.init()
        }
      },
      deep: true //对象内部属性的监听,关键。
    }

以下是我自己渲染出来的图

vue echarts动态刷新数据(x轴y轴和title)

最近需求做一个数据表,根据筛选条件不一样,渲染不同的内容。

主要如下图

如图,一开始什么都没有的时候默认显示title,当进行筛选的时候横轴和纵轴都显示相应的数据。

问题就是,我按照其他百度问题说的做,直接赋值语句上this.chart.setOption(newVal);

然而并没有什么用。。。。。

因为需求是有数据时改变x轴和y轴数据,隐藏标题的渲染,百度到几乎都是差不多一样的解法之后,,,,我放弃了百度,自己上,因为之前有做echarts的经验,所以摸索起来花了一个多小时把它整出来了,最关键代码先贴出来,心急的小伙伴看完就差不多可以自己撸起袖子干了。

axiasy: function(newVal, oldVal) {
      console.log(newVal, oldVal)
      this.chart.clear()  // 清空echarts之前渲染的数据
      this.lineOption.series[0].data = this.axiasy  //赋值y轴
      this.lineOption.xAxis[0].data = this.axiasx   //赋值x轴
      this.lineOption.title.show = this.emptyshow    //标题的展示和隐藏
      this.chart.setOption(this.lineOption, true)    //赋值好之后将数据set进去完事
    }

上面就是我研究出来的,哈哈,满足需求就很爽!

人狠话不多,上代码(由于某种原因,echarts的线图是直接抽出来的插件,so我把它展示一下,觉得难以理解可以看别人的渲染,只是修改的时候渲染的时候看这个就行)

<template>
  <div :id="id" :class="className" :axiasx="axiasx" :axiasy="axiasy" :style="{height:height,width:width}" />
</template>
<script>
import echarts from 'echarts'
import resize from './mixins/resize'
export default {
  mixins: [resize],
  props: {
    className: {
      type: String,
      default: 'chart'
    },
    id: {
      type: String,
      default: 'chart'
    },
    width: {
      type: String,
      default: '200px'
    },
    height: {
      type: String,
      default: '200px'
    },
    axiasx: {
      type: Array,
      default: () => []
    },
    axiasy: {
      type: Array,
      default: () => []
    },
    emptyshow: {//展示标题与否
      type: Boolean,
      default: true
    },
    titles: {//是否输入不同的标题提示
      type: String,
      default: ''
    }
  },
  data() {
    return {
      chart: null,
      lineOption: {
        backgroundColor: '#394056',
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            lineStyle: {
              color: '#57617B'
            }
          },
          formatter: '时间:{b} \n 使用率:{c}%'
        },
        title: {
          text: '暂无数据,选择医院及日期后将自动渲染',
          show: this.emptyshow,
          textStyle: {
            color: '#fff',
            fontSize: 16
          },
          textAlign: 'middle',
          top: '50%',
          left: '45%'
        },
        grid: {
          top: 100,
          left: '5%',
          right: '5%',
          bottom: '3%',
          containLabel: true
        },
        xAxis: [{
          type: 'category',
          boundaryGap: false,
          name: '时间',
          nameTextStyle: {
            color: 'rgb(0,253,255,0.6)',
            fontSize: 16
          },
          axisLine: {
            lineStyle: {
              color: 'rgb(23,255,243,0.3)'
            }
          },
          axisLabel: {
            margin: 10,
            textStyle: {
              fontSize: 14,
              color: '#fff'
            }
          },
          data: this.axiasx
        }],
        yAxis: [{
          type: 'value',
          name: '使用率(%)',
          nameTextStyle: {
            color: 'rgb(0,253,255,0.6)',
            fontSize: 16
          },
          max: 100,
          axisTick: {
            show: false
          },
          axisLine: {
            lineStyle: {
              color: 'rgb(23,255,243,0.3)'
            }
          },
          axisLabel: {
            margin: 10,
            textStyle: {
              fontSize: 14,
              color: '#fff'
            }
          },
          splitLine: {
            lineStyle: {
              color: 'rgb(23,255,243,0.3)'
            }
          }
        }],
        series: [{
          name: '使用率',
          type: 'line',
          // smooth: true,//是否需要曲线平滑
          symbol: 'circle',
          symbolSize: 5,
          lineStyle: {
            normal: {
              width: 1
            }
          },
          areaStyle: {
            normal: {
              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
                offset: 0,
                color: 'rgba(23, 255, 243, 0.5)'
              }, {
                offset: 0.8,
                color: 'rgba(23, 255, 243, 0)'
              }], false),
              shadowColor: 'rgba(0, 0, 0, 0.1)',
              shadowBlur: 10
            }
          },
          itemStyle: {
            normal: {
              color: 'rgba(23, 255, 243)',
              borderWidth: 12,
              label: {
                show: true,
                position: 'top',
                textStyle: {
                  color: '#fff',
                  fontSize: 14
                },
                formatter: '{c}%'
              }
            }
          },
          data: this.axiasy
        }]
      }
    }
  },
  watch: {
    axiasy: function(newVal, oldVal) {
      console.log(newVal, oldVal)
      this.chart.clear()
      this.lineOption.series[0].data = this.axiasy
      this.lineOption.xAxis[0].data = this.axiasx
      this.lineOption.title.show = this.emptyshow
      this.chart.setOption(this.lineOption, true)
    },
    titles: function(newVal, oldVal) {
      console.log(newVal, oldVal)
      this.chart.clear()
      this.lineOption.title.text = this.titles
      this.chart.setOption(this.lineOption, true)
    }
  },
  mounted() {
    this.initChart()
  },
  beforeDestroy() {
    if (!this.chart) {
      return
    }
    this.chart.dispose()
    this.chart = null
  },
  methods: {
    initChart() {
      this.chart = echarts.init(document.getElementById(this.id))
      this.chart.setOption(this.lineOption)
    }
  }
}
</script>

由于引入了mixins/resize,所以也把它贴出来

export default {
  data() {
    return {
      $_sidebarElm: null
    }
  },
  mounted() {
    this.__resizeHandler = this.debounce(() => {
      if (this.chart) {
        this.chart.resize()
      }
    }, 100)
    window.addEventListener('resize', this.__resizeHandler)
    this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
    this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.__resizeHandler)
    this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
  },
  methods: {
    // use $_ for mixins properties
    // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
    $_sidebarResizeHandler(e) {
      if (e.propertyName === 'width') {
        this.__resizeHandler()
      }
    },
    debounce(func, wait, immediate) {
  let timeout, args, context, timestamp, result
  const later = function() {
    // 据上一次触发时间间隔
    const last = +new Date() - timestamp
    // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
    if (last < wait && last > 0) {
      timeout = setTimeout(later, wait - last)
    } else {
      timeout = null
      // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
      if (!immediate) {
        result = func.apply(context, args)
        if (!timeout) context = args = null
      }
    }
  }
  }
}

主组件就根据条件传参进来即可

<div class="chart-container">
        <chart height="92%" width="100%" :axiasx="axiasx" :axiasy="axiasy" :emptyshow="emptyShow" :titles="noneTitle" />
      </div>
<script>
import Chart from '@/components/Charts/LineMarker'
import { Message } from 'element-ui'
import { fetchEcharts, fetchClassTable, fetchhospitalList } from '@/api/api-request'
export default {
  name: 'TabPane',
  components: { Pagination, Chart },
  props: {
    type: {
      type: String,
      default: 'et'
    }
  },
  data() {
    return {
      selectValue: null, // 选择的医院
      options: [],
      axiasx: [],
      axiasy: [], // 画图的y轴
      emptyShow: true, // 定义是否已经可以渲染
      sortValue: '', // 排序条件选择
      noneTitle: '', // 选择查看的图表没有数据
      dateValue: [new Date(new Date().getTime() - 3600 * 1000 * 24), new Date()],
      listLoading: false, // 加载数据回来后变为false
      listQuery: {
        page: 1,
        limit: 20,
        total: 12
      },
      tableData: []
    }
  },
  created() {
    this.getHospital()
  },
  methods: {
    getHospital() {
        fetchhospitalList().then(res => {
          console.log(res)
          if (res.errcode === 0) {
            this.options = res.hospital_list
            const list = getHosMessage(res)
            this.$store.commit('hospital/SET_HOSPITAL_LIST', list[0])
            this.$store.commit('hospital/SET_DEPARTMENT_LIST', list[1])
            this.$store.commit('hospital/SET_ORGINHOSPITAL_LIST', res.hospital_list)
          }
          this.loading = false
        }) 
    },
    getList() {
       // 只是折线图
        const params = { 'page': this.listQuery.page, 'hospital_id': this.selectValue, 'start_date': this.dateValue[0], 'end_date': this.dateValue[1] }
        fetchEcharts(params).then(res => {
          console.log(res)
          if (res.errcode === 0) {
            const arrx = []
            const arry = []
            const item = res.use_rate_list
            if (item.length > 0) {
              for (let i = 0; i < item.length; i++) {
                arrx.push(item[i].day)
                arry.push(parseFloat(item[i].use_rate) * 100)
              }
              this.axiasx = arrx
              this.axiasy = arry
              this.emptyShow = false
            } else {
              console.log('我是没有数据的显示')
              this.noneTitle = '抱歉!您选择的医院在本时间段并没有数据~'
              this.emptyShow = true
            }
          }
        })
        console.log(this.dateValue)// 筛选的日期
    },
    handleFilter() {
      if (!this.selectValue) {
        Message({
          message: '请选择需要查看的医院!',
          type: 'error',
          duration: 2 * 1000
        })
        return
      } else if (!this.dateValue) {
        Message({
          message: '请选择需要查看的时间段!',
          type: 'error',
          duration: 2 * 1000
        })
        return
      }
      this.getList()
    }
  }
}
</script>

最终经过筛选条件出来后,显示如下:

有数据时显示

没有数据时显示

最后,不要问我为什么不直接调用init函数,因为重新渲染dom节点是需要付出代价的!!!!

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文