likes
comments
collection
share

React项目🌹Echarts踩坑记录🌹

作者站长头像
站长
· 阅读数 58

React项目🌹Echarts踩坑记录🌹

项目背景

最近在做一个react项目,在首页里面放置多个Echarts图表,并支持下载(可支持导出图片或者表格),查看更多(点击图表上方的查看更多按钮,打开抽屉,显示全部数据,数据可能很多),截止到今天,差不多已经完成了页面的编写和接口调试。

在做需求的过程中,也遇到了与Echarts相关的一些问题。这篇文章主要是记录这些问题。

主要遇到的问题,有以下四个:

  • 查看更多,抽屉打开,图表尺寸异常
  • 切换页签,鼠标返回页面,图表异常消失
  • 在调试过程中,接口重复调用
  • Echarts图表导出功能实现

抽屉尺寸异常

问题描述

首页里有一个小的图表,里面包含7个部门的柱状图数据,图表上方有一个查看更多按钮,点击按钮,打开一个抽屉,显示全部部门的数据,部门可能很多,100%高度可能会使得数据显示很拥挤,单个柱体最小是35px。

但是刚一进入,抽屉里面的图表很小很小,设置的高度100%和宽度100%没有生效。打开控制台,控制台报Echarts提醒:

echarts警告:Can't get DOM width or height. Please check dom.clientWidth and dom.
clientHeight. They should not be 0.For example, 
you may need to call this in the callback of window.onload.

错误翻译:

无法获取dom的宽高(简单来说就这个几个字)
翻译:无法获取DOM的宽度或高度。请检查dom。clientWidth dom.clientHeight。它们不应该是0
例如,你可能需要在window.onload的回调函数中调用它。

解决方案

这里通过在useEffect() 中借助setTimeout()来延迟加载。

一定要在DOM渲染结束后,再去加载

核心代码:

const [chartHeight, setChartHeight] = usestate('100%')

useEffect(() => { 
  const { lineData, yData } = echartsData
  const chartHeightTime = setTimeout(() => {
    //解决数据量过大时,全屏显示密集的问题
    const rawHeight = allDepartmentRef.current?.getBoundingClientRect()?.height
    if (rawHeight && yData?.length) {
      const chartHeight = yData.length * 35
      const height = chartHeight > rawHeight ? `${chartHeight}px` : '100%'
      setChartHeight(height)
    } 
  }, 50)
  
  // 延时加载,避免获取不到元素的高与宽
  const chartInitTime = setTimeout(() => {
    // 在组件挂载或更新时,创建或更新图表
    if (allDepartmentRef?.current) {
      myChart.current = echarts.init(allDepartmentRef.current)
      //配置图表选项
      const options = updateOptions(lineData, yData)

      // 使用指定的配置项和数据显示图表
      myChart.current?.setOption(options)
      window,addEventListener('resize', echartsResize, false)
    }
  }, 200)
  
  return () => {
    clearTimeout(chartHeightTime)
    clearTimeout(chartInitTime)
  }
},[echartsData])


<div ref={allDepartmentRef} style={{ width: '100%',height: chartHeight }}></div>

切换页签,Echarts图表消失

问题描述

那问题是什么原因引起的呢?排查了半天,在网上也找了好多方法,也没解决。

解决方案

最后使用了一个笨办法,既然切换页面,原页面不可视,再切换到首页页面,页面可视,那没有方法来进行监听这种情况呢,答案是有的:document.addEventListener('visibilitychange')

document.addEventListener('visibilitychange')是一个事件监听器,它用于检测网页的可见性发生变化时触发的事件。

当用户离开当前页面,或者最小化当前窗口,或者切换到了其他标签页,这个事件会被触发。网页可以通过这个事件来实现一些特定的行为,比如自动暂停视频播放、减少后台网络请求等。

使用方法如下:

document.addEventListener('visibilitychange', function() {
  if (document.hidden) {
    // 页面不可见时执行的代码
  } else {
    // 页面可见时执行的代码
  }
});

在以上代码中,当页面状态发生变化时,回调函数里的代码会被执行。由于document.hidden属性可以返回当前页面的可见性状态,因此我们可以根据该属性的值来判断页面是否可见,并执行相应的代码。

核心代码:

//重新进入页面标识,用于处理页面重新进入时,页面图表不显示的问题
const [isOnPage, setIsOnPage] = useState < boolean > (true)

useEffect(() => {
  const handleVisibilityChange = () => {
    if (document.visibilityState === 'visible') {
      setIsOnPage(true)
    } else if (document.visibilityState === 'hidden') {
      setIsOnPage(false)
    }
  }

  document.addEventListener('visibilitychange', handleVisibilityChange)

  return () => {
    document.removeEventListener('visibilitychange', handleVisibilityChange)
  }
}, [])

// 组件使用
useEffect(() => {
  ...
  if (isOnPage) {
    setoptions(echartsoptions)
  }
}, [isOnPage])

调用调用,重复请求

问题描述

在联调后台接口的时候,后台接口一直报重复请求的错误(项目中做了重复请求的拦截和错误提示),一个页面里面包含十几个图表,初始进入时,要调用十几个接口,这些接口都报了重复请求的错误。但是部署到测试环境就正常。

后面进行排查,也是没排查出来问题所在。最后请教了别人,才知道是因为:

React中StrictMode严格模式,会导致开发环境,接口会请求两次或多次( useEffect 请求多次)。

唉,还是学react不够深,以后要多多学习,积累经验。

解决方案

React 提供了 严格模式,在严格模式下开发时,它将会调用每个组件函数两次。通过重复调用组件函数,严格模式有助于找到违反这些规则的组件。

问题定位了,那这个问题就很好解决了。直接不用StrictMode严格模式不就行了吗。

root.render(
   // <React.StrictMoide>
        <App />
   // </React.StrictMoide>
)

图表下载

问题描述

图表中的下载是支持下载图表和表格的,但是Echarts图表原生带入的下载功能,只支持下载图片,是不支持下载表格的。

解决方案

这里我们可以利用定位,在图表上方放一个下载按钮,鼠标悬浮,会有下载格式选择,选择图片,调用Echarts自带的原生下载方法,选择表格,调用后台接口即可。

那怎么调用Echarts的原生下载图片功能呢。

实现代码:


import * as echarts from "echarts";

const exportEchart = (fileName: String, echartsRef: any) => {
  const myChart: any = echarts.getInstanceByDom(echartsRef as any);
  const url = myChart.getConnectedDataURL({
    pixelRatio: 2, //导出的图片分辨率比率,默认是1
    backgroundColor: "#fff", //图表背景色
    excludeComponents: [
      //保存图表时忽略的工具组件,默认忽略工具栏
      "toolbox",
    ],
    type: "png", //图片类型支持png和jpeg
  });
  const $a = document.createElement("a");
  const type = "png";
  $a.download = `${fileName}.${type}`
  $a.target = "_blank";
  $a.href = url;
  // Chrome and Firefox
  if (typeof MouseEvent === "function") {
    const evt = new MouseEvent("click", {
      view: window,
      bubbles: true,
      cancelable: false,
    });
    $a.dispatchEvent(evt);
  }
  // IE
  else {
    const html =
      "" +
      '<body style="margin:0;">' +
      '<img src="' +
      url +
      '" style="max-width:100%;" title="' +
      myChart.getOption().title[0].text +
      '" />' +
      "</body>";
    const tab: any = window.open();
    tab.document.write(html);
  }
}

export default exportEchart

// 使用
exportEchart('用户所属部门', allDepartmentRef.current)

< div ref = { allDepartmentRef } style={{height:'100%', width:'100%'}}></>
转载自:https://juejin.cn/post/7374307181482213430
评论
请登录