Vue3 中 echarts resize() 不生效

背景

最近在用 Vue3 开发一个可视化页面时发生了个奇怪的现象,想实现图表在用户调整窗口大小后重新渲染,防止发生变形,已经在元素上设置了百分比宽高,但它就是不生效。

解决方案

不多废话,先说解决方案。其实很简单,只需要将你的 echarts 实例对象用 shadowRef() 进行创建,而不是使用坑人的 ref()

原来的写法

js 复制代码
import * as echarts from 'echarts';
import { onMounted, ref } from 'vue';

// !!!重点就在这里!!!
const chart = ref(null);

onMounted(() => {
  initChart();
  // 添加窗口大小变化监听
  window.addEventListener('resize', handleResize);
});

const initChart = () => {
	const options = { .....};
	const chartDom = document.getElementById('chart');
    chart.value = echarts.init(chartDom);
    chart.value.setOption(options);
  }
}

// 处理窗口大小变化
const handleResize = () => {
  chart.value && chart.value.resize();
};

修复后写法

js 复制代码
......保持不变
import { onMounted, shadowRef } from 'vue';

// !!!重点就在这里!!!
const chart = shadowRef(null);
...保持不变

寻找原因

改完之后生效并且不想关注原因的兄弟可以关闭网站继续搬砖了。

元素宽高百分比?

刚开始我从网上找到的解决方案都是围绕在 echarts 所在元素不能设置固定宽高这个问题上,我的写法确实也不对,但是我将宽高改成百分比之后还是不行,并且在浏览器控制台发现了一个奇怪的报错: echart.resize LineView seriesModel.coordinateSystem undefined

coordinateSystem?

基于这个关键词,我又找到了 echarts Github 仓库的 issues 列表里,在这里找到了我们最终的解决方案,感谢这位大善人🙏。

github.com/apache/echa...

shadowRef ?

这又是个什么 API?我怎么没学过?

既然遇到了,那就学学吧。

shallowRef 在 Vue 3 中用于创建一个 Ref 对象,但是它不会将对象内部的属性进行深层响应式化。这意味着,当对象本身被替换时,shallowRef 会触发更新,但对象内部的属性发生变化时不会触发更新。 使用场景:

  1. 性能优化: 对于大型对象,尤其是在对象内部的属性变化不应该影响视图更新的情况下,使用 shallowRef 可以提高性能,减少不必要的更新。
  2. 与第三方库集成: 当你需要将第三方库的对象暴露给组件,并且第三方库的API可能导致对象内部的属性变化,但你不需要让组件对这些变化进行响应时,shallowRef 可以帮助你避免不必要的更新和性能问题。
  3. 临时读取: 当你只需要临时读取某个对象的数据,而不需要对这个对象进行响应式跟踪时,shallowRef 可以避免不必要的跟踪开销。

shadowRef 与 ref 的区别:

  • ref 会将对象内部的属性进行深层响应式化,即对象内部任何属性的改变都会导致视图更新。
  • shallowRef 只对对象本身进行响应式化,对象内部的属性变化不会触发视图更新。

个人理解可能是 ref 的深层响应化破坏或影响了 echarts 对象本身,从而导致 echarts 实例中的某些方法失效。

总结

刚才我说 ref 坑人其实有失偏颇,大家还是要根据使用场景来选择到底要用哪个 API,显然这个场景下 shadowRef 是好用的。

Vue3,你就学吧~

相关推荐
WindfallSheng1 小时前
从Vibe Coding到Spec Coding:一套可落地的AI-SDD企业级研发实战工程
javascript·vue.js
我有满天星辰2 小时前
Vue 指令完全指南:从 Vue 2 到 Vue 3 的演进与实战
前端·javascript·vue.js
我有满天星辰4 小时前
Vue 3 响应式双雄:ref 与 reactive 完全指南
前端·javascript·vue.js
leoZ23115 小时前
Claude 驱动的全栈开发:Spring Boot + Vue 的 BS 架构实践
vue.js·spring boot·架构
荒诞英雄19 小时前
从 17MB Vendor 大包到按需加载:Vite 多入口 Vue 组件库首屏优化实践
vue.js·vite
jsonbro19 小时前
手把手带你实现发布订阅模式
前端·vue.js·设计模式
Cobyte21 小时前
23.Vue Vapor 组件 attrs 的实现
前端·javascript·vue.js
斯特凡今天也很帅1 天前
xml页面可以打开,不报错,但是显示数据的地方也不显示,我是怎么解决的
xml·vue.js
柯克七七1 天前
给老项目加了 TypeScript,本来只想自己爽,结果全公司代码审查标准被我抬高了
前端·vue.js·typescript
自然 醒1 天前
前端如何实现在线预览office常见文件功能?
前端·vue.js