ecomfe / vue-echarts

Vue.js component for Apache ECharts™.
https://vue-echarts.dev
MIT License
9.43k stars 1.48k forks source link

build后无法获取echart的实例 #786

Closed Preyou closed 1 month ago

Preyou commented 1 month ago

请确认

您是如何将 Vue-ECharts 引入项目的?

通过 ES 模块 import

版本信息

dependencies:
echarts 5.5.0
vue 3.4.27
vue-echarts 6.7.2

问题详情

在dev环境下一切正常,但是build后,无法通过ref获取vueEchart的实例

以下是一个最小复现案例

https://github.com/Preyou/vue-project

分别运行dev,和build后的preview,打开控制台对比输出。

对于以下简单的测试代码

<script setup>
import VueChart from 'vue-echarts'
import {ref} from 'vue'
import HelloWorld from './components/HelloWorld.vue'

const a = ref()
console.log(a);

const b = ref()
console.log(b);
</script>

<template>
  <VueChart ref="a"></VueChart>
  <HelloWorld ref="b" />
</template>

dev模式下正确拿到实例: image

preview模式下的异常实例: image

问题复现

https://github.com/Preyou/vue-project

Justineo commented 1 month ago

复现代码输出不了你截图的日志吧。

Preyou commented 1 month ago

复现代码输出不了你截图的日志吧。

我仓库的代码复现不了吗

Preyou commented 1 month ago

复现代码输出不了你截图的日志吧。

两次截图分别是打包前和打包后a的值

b的值是正常的,我就没截图

Justineo commented 1 month ago

我仓库的代码复现不了吗

复现不了,你检查一下吧

Preyou commented 1 month ago

我仓库的代码复现不了吗

复现不了,你检查一下吧

可以复现啊

image

我准备了个在线的 https://stackblitz.com/~/github.com/Preyou/vue-project?file=src/App.vue

Preyou commented 1 month ago

我仓库的代码复现不了吗

复现不了,你检查一下吧

可以复现啊

image

我准备了个在线的 https://stackblitz.com/~/github.com/Preyou/vue-project?file=src/App.vue

直接运行 pnpm run preview 再看控制台就可以发现,没有正确的获取实例

Justineo commented 1 month ago

mount 以前 ref 的 value 应该是 undefined 吧,你这么写如果能取到值那肯定是因为热更新导致的。这在生产环境肯定不对啊。

Preyou commented 1 month ago

mount 以前 ref 的 value 应该是 undefined 吧,你这么写如果能取到值那肯定是因为热更新导致的。这在生产环境肯定不对啊。

我这么写是没问题的,我打印的是ref而不是ref.value。而且就算是把log写在onMounted里,一样不行。

Justineo commented 1 month ago

我试了一下在 preview 下取到组件实例是没有问题的,你不要看 console 打出来的内容,你试试实际调用实例上的方法看看。

Preyou commented 1 month ago

我试了一下在 preview 下取到组件实例是没有问题的,你不要看 console 打出来的内容,你试试实际调用实例上的方法看看。

确实是可以调用的,但是属性不可枚举还是有点问题的,在实现组件继承时,为了连expose一起继承,我可能会这么写

const chart = reactive({})

defineExpose(chart)

onMounted(()=>{
  Object.assign(chart, chartInstance.value)
})

这里当然可以改成

defineExpose({
  chart: chartInstance
})

但是这样写的话,每次调用包装后的组件都得多访问一层chart

包装前

const echart = ref()

onMounted(()=>{
   echart.value.dispatchAction({})
})

包装后

const echart = ref()

onMounted(()=>{
   echart.value.chart.dispatchAction({})
})

但是我包装组件的目的主要是为了全局覆写一些默认参数(比如theme),避免每个调用的地方都要再写一遍。并不想改变原有组件的用法,以便其他开发人员可以在仅参考原有文档的基础上就能使用包装后的组件。

而且我不太清楚为何这个组件打包后所有的实例属性都不可枚举了,这使得某些依赖迭代器的用法都会在打包前后的表现不一致。比如for in...objObject.assignObject.keysObject.valuesObject.entries等,都将无法在打包后正确拿到属性。

Justineo commented 1 month ago

这个和 Vue ECharts 无关的,你搞一个只包含 Vue 的项目试一下,也是这样的。

Preyou commented 1 month ago

这个和 Vue ECharts 无关的,你搞一个只包含 Vue 的项目试一下,也是这样的。

我在示例里不是还打印了一个变量b吗,这个b就是正常可枚举的。

image

Justineo commented 1 month ago

你搞一个不是通过 defineExpose 定义的实例。