react动态渲染echarts出现无法渲染问题的调试与思考

阅读: 评论:0

react动态渲染echarts出现无法渲染问题的调试与思考

react动态渲染echarts出现无法渲染问题的调试与思考

react动态渲染echarts出现无法渲染问题的调试与思考

  • 业务背景
  • 出现的问题
  • 问题解决
    • 元素检查
    • 问题原因
    • 原因检验
    • 问题解决
  • 拓展

业务背景

需要制作一个报表,当返回数据为空时显示暂无数据,当数据不为空时,展示echarts图表;

贴一下复现问题的demo

import './App.css';
import {Button} from 'antd'
import { useEffect, useState } from 'react';
const echarts = require('echarts')function App() {const [num, setNum] = useState(0);function change(){if(num) setNum(0);else setNum(1);}useEffect(() => {if(num !== 0){let x = [1,2,3];let y = [1,1,1];let chart = ElementById('chart');let myChart = echarts.init(chart);myChart.setOption({xAxis: {data: x},yAxis: {},series: [{type: 'bar',data: y}]})}}, [num])return (<div><div style={{display: 'flex'}}><div style={{marginRight: '20px'}}>num: {num}</div><Button onClick={change} type='primary'>改变</Button></div>{  num === 0 ? <div id='dataNone'>暂无数据</div> : <div id='chart' style={{width: '200px', height: '200px'}}></div>}</div>);
}export default App;

出现的问题

当渲染echarts图表后,之后再次出现渲染暂无数据,之后再次需要渲染echarts图表时无法渲染。
初始化状态:

首次渲染echarts图表:

再次渲染暂无数据:

再次需要渲染图表时出现无法渲染的问题:

问题解决

元素检查

我们使用开发者工具对页面元素进行检查
初始化状态:

首次渲染echarts图表:

再次渲染暂无数据:我们可以看到奇怪的事情出现了,暂无数据所在的div上也有了echarts_instance属性

再次需要渲染图表时出现无法渲染:

问题原因

由于我们没有对echarts图表进行销毁操作,所以导致echarts_instance属性一直存在,并且由于react在更新页面时使用diff算法进行最小化更新,此处在暂无数据和echarts图表进行切换时,react会认为该div是可以复用的,所以不会清除div和重建div,而是选择将旧div上的属性(并不包括所有属性,例如id就不会)移到新div上并更新div里的内容。
所以当从首次渲染echarts图表切换到暂无数据时,暂无数据所在的div上会有echarts_instance属性,而再次切换到echarts图表进行初始化时,echarts发现该div上已经有了echarts_instance属性,并且该div之前放的是文本,破坏了该div的结构,所以出现不渲染的问题。(若div内一直存放的是echarts实例,那么重新渲染不会出现问题)

原因检验

给两个div添加上不同的key,发现不再出现问题,证明是最小化更新时将两个div判断为相同节点而导致不是删除旧节点并创建新节点,而是对节点进行复用,并将属性和内容进行移植。

<div><div style={{display: 'flex'}}><div style={{marginRight: '20px'}}>num: {num}</div><Button onClick={change} type='primary'>改变</Button></div>{  num === 0 ? <div id='dataNone' key='dataNone'>暂无数据</div> : <div id='chart' style={{width: '200px', height: '200px'}} key='chart'></div>}
</div>

问题解决

1、保持严谨性,遇到这种业务场景时一定要记得在切换之前将图表销毁,有两种方法:
使用echarts方法

echartsInstance.clear
echartsInstance.dispose

手动去除该属性

veAttribute('_echarts_instance_')

2、绕过react的最小化更新
1)使用两个div,用js监控变量并分别控制其display属性来切换图表和暂无数据

<divid="chart"style={{display: 'none',height: '400px',width: '620px',}}
> </div>
<div id='dataNone'>暂无数据
</div>

2)如上所述,给两个div添加不同且唯一的key值,防止被判断成相同节点

拓展

react的diff可能发生在任意一个页面刷新时,但我们使用到key的场景极为有限(对数组进行遍历渲染相同结构的多组dom时使用key来节省性能等),然而为什么出现问题的情况仍然非常少呢?这是因为大多数情况下diff更新后的dom结构并不会对下一次diff更新的dom结构产生影响,即使是上述情况(对数组进行遍历渲染相同结构的多组dom时使用key来节省性能),也不会产生问题,只不过是增加页面刷新的开销而已。
所以我们在刷新页面时应该关注以下两点来适应diff:
1、减小页面组件对dom的依赖(无论该dom之前是什么样子,组件都可以渲染到该dom中去)
2、通过使用key来进行真正意义上的更新,而不是diff对旧dom进行复用

本文发布于:2024-02-02 21:17:37,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170687985746495.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:动态   react   echarts
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23