ant.design React使用Echarts,实力踩坑

最近项目用到Echarts(以下用ec代替),于是照猫画虎得引入到团队的antd项目中,但是遇到2个棘手问题:

  1. ec对dom不渲染,检查后发现,原来是全局存在id重复,所以使用React时,最好对使用id保持全局唯一,说个题外话,其实 会用到id的机会少之又少。

  2. ec报错:Cannot read property 'getAttribute' of null ,因为ec需要一个渲染挂载点,而用getById时,总是获取不到。

3.Component series.scatter not exists. Load it first. 是echart的引入问题

  先说一下需求,我要实现点击按钮弹一个框 modal,框里有一个柱形图,用于展示一些数据,正是由于弹框是需要时才会渲染存在的,因此就会出现找不到该DOM节点的情况,说是ec问题,实际上还是React问题。

  网上找了很久,有说用componentDidmount的,有说用 window.onload 的,有说用setTimeout延迟一下再获取的,可能是我的需求比较刁钻,统统不行,花了4小时实力踩坑,最后回归到文档,终于找到解决办法了,灵感来源:https://react.docschina.org/docs/refs-and-the-dom.html

解决方案只涉及React提供的东西足够:ref,无须用到id,window.onload之类的

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);

    this.textInput = null;

    this.setTextInputRef = element => {
      this.textInput = element;
    };

    this.focusTextInput = () => {
      // 直接使用原生 API 使 text 输入框获得焦点
      if (this.textInput) this.textInput.focus();
    };
  }

  componentDidMount() {
    // 渲染后文本框自动获得焦点
    this.focusTextInput();
  }

  render() {
    // 使用 `ref` 的回调将 text 输入框的 DOM 节点存储到 React
    // 实例上(比如 this.textInput)
    return (
      <div>
        <input
          type="text"
          ref={this.setTextInputRef}
        />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focusTextInput}
        />
      </div>
    );
  }
}

我稍微加以改造,呈现如下:

注意:这是modal里的代码,modal是会被生成或销毁的,因此需要多次生成图表

 return (
      <Modal {...modalOpts}>
        <Row {...rowProps}>
          <Col span={24}>
            <div ref={this.setTextInputRef} 500px', height: '500px' }}></div>
          </Col>
        </Row>
      </Modal>
    )
  setTextInputRef(element) {

    if (element) {
      // 基于准备好的dom,初始化echarts实例
      const dom = element
      var myChart = echarts.init(dom)
      // 绘制图表
      myChart.setOption({
        title: { text: 'ECharts 入门示例' },
        tooltip: {},
        xAxis: {
          data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"]
        },
        yAxis: {},
        series: [{
          name: '销量',
          type: 'bar',
          data: [5, 20, 36, 10, 10, 20]
        }]
      })
    }
  };

这里是借用ref,虽说不是很棒的解决方案,但是是我目前找到最简单的解决办法!