uni-app中直接import * as echarts from 'echarts'在非H5端必报ReferenceError: window is not defined,因ECharts依赖浏览器全局对象;renderjs运行在视图层,具备完整DOM环境,是当前最稳跨端方案。

uni-app 里直接 import * as echarts from 'echarts' 然后调用 echarts.init(),在小程序和 App 端必然报错:ReferenceError: window is not defined。这不是代码写错了,而是 ECharts 默认依赖浏览器全局对象,而 uni-app 的非 H5 端(微信/支付宝小程序、App)根本没有 window 和 document。
为什么 renderjs 是当前最稳的跨端方案
renderjs 运行在视图层(WebView),天然拥有完整的浏览器环境,window、document、canvas 全都有,ECharts 可以原样运行。逻辑层(Vue 组件)只负责传数据和收事件,不碰渲染——这避免了平台判断、条件编译、手动 canvas 初始化等一堆胶水代码。
- 不需要为微信小程序单独引入
echarts-for-weixin,也不用复制ec-canvas组件 - 不用在 H5 端等
onReady或$nextTick,renderjs 自动等 DOM 就绪 - App 端动画卡顿、tooltip 不响应、dataZoom 拖不动等问题,renderjs 下基本消失(因走的是真实 DOM 渲染路径)
- 但注意:nvue 页面不支持 renderjs,仅适用于 vue 页面
renderjs 中初始化 ECharts 的关键三步
renderjs 文件必须放在 components/ 目录下,且后缀为 .renderjs(如 components/echarts.renderjs),否则不会被识别为 renderjs 模块。
ECharts 图表大师。根据用户数据和业务上下文,自动设计并生成专业的 ECharts 可视化图表。使用场景:(1) 用户提供表格/JSON/CSV 数据需要可视化,(2) 用户说"帮我做个图"、"画个图表",(3) 需要将查询结果可视化展示。
- 第一步:在 renderjs 中通过
require加载 ECharts(不能用import):const echarts = require('@/static/echarts.min.js')—— 建议把压缩版echarts.min.js放到static/目录,避免构建时被 babel 处理出错 - 第二步:监听逻辑层发来的
init消息,拿到容器 id 后调用echarts.init(document.getElementById(id)),并缓存实例(如this.chart = chart) - 第三步:收到
setOption消息时,直接调用this.chart.setOption(option, { notMerge: false });若需响应点击事件,提前注册chart.on('click', ...)并用uni.$emit把事件透传回逻辑层
逻辑层如何安全传参与更新图表
Vue 组件不能直接操作 renderjs 中的 chart 实例,所有交互必须走消息通信。常见错误是把整个 option 对象频繁全量发送,导致性能下降或内存泄漏。
- 不要在
v-for循环里反复调用this.$scope.call('init')—— 初始化一次即可,后续只调setOption - 动态数据更新时,优先用
setOption({ series: [...] }, { notMerge: true }),避免重绘坐标轴、图例等静态部分 - 如果
option里含函数(如formatter),必须序列化为字符串再传过去,renderjs 中用eval或new Function恢复(有安全风险,建议尽量用纯 JSON 配置) - 组件
beforeDestroy或unmounted钩子中,务必调用this.$scope.call('dispose'),让 renderjs 执行chart.dispose(),否则内存持续增长
绕不开的兼容性细节
即使用了 renderjs,有些配置项在小程序里依然会失效或表现异常,不是 bug,是底层 canvas 渲染限制。
-
tooltip.trigger: 'axis'在微信小程序中 hover 无反应,必须改用'item'或禁用 tooltip -
animation: true在低端安卓机上极易卡顿,建议设为false,或用animationDurationUpdate: 300控制更新动画时长 - 使用
graphic组件(如自定义图片、文字)时,style.image必须是本地绝对路径(/static/logo.png),网络地址不生效 - 打包后主包超限?把
echarts.min.js放到static/目录可避免被 webpack 打包进主包,但需手动维护版本
真正难的不是“怎么让图表显示出来”,而是“怎么让不同平台下的交互行为一致、内存不泄露、更新不卡顿”。renderjs 提供了统一运行环境,但配置项的平台差异、数据更新策略、生命周期管理这些细节,才是决定图表组件是否能长期稳定复用的关键。

















