vue3 封装了折线图组件,但是数据变化更新的时候折线图不更新?

lineChart 组件代码

<template>
  <div :id="name" :style="echartStyle"></div>
</template>
<script setup lang='ts'>
import { onBeforeUnmount, onMounted, ref, toRef, watch } from 'vue'

import * as Echarts from 'echarts'
const prop = defineProps({
  name: String,
  echartStyle: Object,
  option: Object,
  onClick: Object
})
let echartsModel = ref(null)
watch(
  () => prop.option,
  () => {
    initEchart()
  }
)
watch(
  () => prop.echartStyle,
  () => {
    if (echartsModel) {
      this.echartsModel.resize()
    }
  }
)

const initEchart = () => {
  echartsModel = Echarts.init(document.getElementById(prop.name))
  echartsModel.clear()
  echartsModel.showLoading('default', {
    text: '加载中',
    color: '#409EFF',
    textColor: '#409EFF',
    maskColor: 'rgba(0, 0, 0, 0.5)',
    zlevel: 0
  })
  echartsModel.setOption(prop.option)
  echartsModel.off('click')
  if (prop.onClick) {
    echartsModel.on('click', (param) => {
      context.emit('chartClick', param)
    })
  }
  echartsModel.hideLoading()
}

const drawResize = () => {
  if (echartsModel) {
    echartsModel.resize()
  }
}
onMounted(() => {
  window.addEventListener('resize', drawResize, 20)
  initEchart()
})
onBeforeUnmount(() => {
  echartsModel.dispose()
  window.removeEventListener('resize', drawResize, 20)
})


</script>

调用代码

  <lineChart :name="echartName" :echartStyle="echartStyle" :option="option" v-show="showLine"></lineChart>

赋值代码

 await queryData(form)
 option.value = setOption(tableData.value);
 showLine.value = true;

注意

let option = ref({});

option 我定义的是 ref的 难道要定义成reactive的空对象????试了 报错

阅读 4.2k
3 个回答

你定义的echartsModel是ref类型的

let echartsModel = ref(null)

试试把它要赋值的地方改成echartsModel.value

const initEchart = () => {
  echartsModel = Echarts.init(document.getElementById(prop.name))
  echartsModel.clear()
  echartsModel.showLoading('default', {
    text: '加载中',
    color: '#409EFF',
    textColor: '#409EFF',
    maskColor: 'rgba(0, 0, 0, 0.5)',
    zlevel: 0
  })
  echartsModel.setOption(prop.option, true) // 设置 notMerge 参数为 true
  echartsModel.off('click')
  if (prop.onClick) {
    echartsModel.on('click', (param) => {
      context.emit('chartClick', param)
    })
  }
  echartsModel.hideLoading()
}

或者:

watch(
  () => prop.option,
  (newOption) => {
    console.log(newOption)
    initEchart()
  }
)

按照你的方法写了个最小demo,并没有发现问题。


图表组件:

<template>
  <div ref="element" class="demo-chart"></div>
</template>

<script lang="ts" setup>
import { ref, shallowRef, watchPostEffect } from "vue";

import type { EChartsOption, EChartsType } from "echarts";
import * as echarts from "echarts";

const props = withDefaults(defineProps<{
  option: EChartsOption
}>(), {});

const element = ref<HTMLDivElement | null>(null);
const instance = shallowRef<EChartsType | null>(null);

function updateCharts() {
  if (instance.value == null) {
    instance.value = echarts.init(element.value);
  }

  instance.value.setOption(props.option);
}

watchPostEffect(() => {
  updateCharts();
});
</script>

<style lang="scss" scoped>
.demo-chart {
  width: 600px;
  height: 400px;
}
</style>

父组件:

<template>
  <div class="container">
    <demo-chart :option="option"></demo-chart>
  </div>
</template>

<script lang="ts" setup>
import { onMounted, ref } from "vue";

import DemoChart from "@/components/DemoChart.vue";

import type { EChartsOption } from "echarts";

const option = ref<EChartsOption>({
  xAxis: {
    type: "category",
    data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
  },
  yAxis: {
    type: "value"
  },
  series: [{
    data: [150, 230, 224, 218, 135, 147, 260],
    type: "line"
  }]
});

onMounted(() => {
  setTimeout(() => {
    option.value.series = [{
      data: [218, 135, 147, 260, 150, 230, 224],
      type: "line"
    }];
  }, 2000);
});
</script>
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题