在react项目中使用ECharts

在react项目中使用ECharts

  这里我们要在自己搭建的react项目中使用ECharts,我们可以在ECharts官网上看到有一种方式是在 webpack 中使用 ECharts,我们需要的就是这种方法。

  我们在使用ECharts之前要先安装ECharts,在以往的开发模式中,我们很多使用就是把官网中的ECharts的核心js文件导入到我们的html或者是jsp等文件里面,但是在react项目中,我们可以直接使用node.js的npm命令安装

npm install echarts --save

  这个时候我们的ECharts就被下载到项目中的node_modules文件夹中,这个时候我们就可以在编写的react组件中使用ECharts了,下面直接看代码:

复制代码
import React, { Component } from 'react';

// 引入 ECharts 主模块
import echarts from 'echarts/lib/echarts';
// 引入柱状图
import  'echarts/lib/chart/bar';
// 引入提示框和标题组件
import 'echarts/lib/component/tooltip';
import 'echarts/lib/component/title';

class EchartsTest extends Component {
    componentDidMount() {
        // 基于准备好的dom,初始化echarts实例
        var myChart = echarts.init(document.getElementById('main'));
        // 绘制图表
        myChart.setOption({
            title: { text: 'ECharts 入门示例' },
            tooltip: {},
            xAxis: {
                data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"]
            },
            yAxis: {},
            series: [{
                name: '销量',
                type: 'bar',
                data: [5, 20, 36, 10, 10, 20]
            }]
        });
    }
    render() {
        return (
            <div id="main" style={{ width: 400, height: 400 }}></div>
        );
    }
}

export default EchartsTest;
复制代码

  这里我们在使用ECharts的时候要在render()方法中return一个有id和大小的div,然后在componentDidMount()方法中像我们以往的方式一样渲染数据,这里都是一些静态的数据,当我们的数据是动态获取的时候,我们就要把渲染ECharts的数据放入到state中,这样我们才能够做出有交互性的动态效果。

  下面是展示代码的效果:

在 React 项目中使用 ECharts

说明

重要文件版本

  • “react”: “^16.2.0”
  • “echarts”: “^4.0.2”
  • “redux”: “^3.7.2”,
  • “react-router-dom”: “^4.2.2”
  • “react-router-redux”: “^5.0.0-alpha.9”
  • “react-hot-loader”: “^4.0.0-beta.21”

在 React 项目中使用 ECharts 生成图表,与使用其他第三方库没有太大的区别,只要在 React 的组件 componentDidMount 声明周期中初始化 ECharts 图表,然后在每次更新组件时调用 ECharts 实例的 setOption() 方法更新配置即可,以下记录了使用当中的一些细节

项目模板源码

编写 <Chart/> 图表组件

>

/*
* ECharts 组件基础部分
* */

import React, { PureComponent } from 'react';
import * as echarts from 'echarts';
import 'zrender/lib/svg/svg';
import throttle from '../../utils/throttle'; // 一个节流函数

export default class Chart extends PureComponent {
    constructor(props) {
        super(props);
        this.state = {
            width: '100%',
            height: '100%'
        };
        this.chart = null;
    }
    /*
        注意:
            虽然在 componentDidMount 中组件已经被装配,
            但是如果设置容器宽高为百分比的值,那么容器的 clientWidth 和 clientHeight 有可能还处于计算中
            这个时候如果在容器中实例化 echarts,echarts 获得的 clientWidth 和 clientHeight 不一定是我们预期的,
            因此这里使用了定时器延迟实例化,也可以提前计算出像素之后 赋值给 width、height,这样不是百分比就没有问题
    */
    async componentDidMount() {
        console.log('did mount');
        // 初始化图表
        await this.initChart(this.el);
        // 将传入的配置(包含数据)注入
        this.setOption(this.props.option);
        // 监听屏幕缩放,重新绘制 echart 图表
        window.addEventListener('resize', throttle(this.resize, 100));
    }
    componentDidUpdate() {
        // 每次更新组件都重置
        this.setOption(this.props.option);
    }
    componentWillUnmount() {
        // 组件卸载前卸载图表
        this.dispose();
    }
    render() {
        const { width, height } = this.state;

        return (
            <div
                className="default-chart"
                ref={el => (this.el = el)}
                style={{ width, height }}
            />
        );
    }
    initChart = el => {
        // renderer 用于配置渲染方式 可以是 svg 或者 canvas
        const renderer = this.props.renderer || 'canvas';
        console.log(renderer);

        return new Promise(resolve => {
            setTimeout(() => {
                this.chart = echarts.init(el, null, {
                    renderer,
                    width: 'auto',
                    height: 'auto'
                });
                resolve();
            }, 0);
        });
    };
    setOption = option => {
        if (!this.chart) {
            return;
        }

        const notMerge = this.props.notMerge;
        const lazyUpdate = this.props.lazyUpdate;

        this.chart.setOption(option, notMerge, lazyUpdate);
    };
    dispose = () => {
        if (!this.chart) {
            return;
        }

        this.chart.dispose();
        this.chart = null;
    };
    resize = () => {
        this.chart && this.chart.resize();
    };
    getInstance = () => {
        return this.chart;
    };
}

其他组件中引用图表组件

/*
   Heatmap 热力图
*/
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import 'echarts/lib/component/tooltip';
import 'echarts/lib/component/title';
import 'echarts/lib/component/grid';
import 'echarts/lib/chart/heatmap';
import 'echarts/lib/component/visualMap';
import Chart from '../components/Chart/index';
import { getChart } from '../modules/charts/actions';

class HeatmapChart extends Component {
    constructor(props) {
        super(props);
        this.state = {
            renderer: 'canvas'
        };
    }
    async componentWillMount() {
        // 装载前 获取数据
        const path = '/heatmap';
        const key = 'heatmap';

        await this.props.getChart({ path, key });
    }
    render() {
        const renderer = this.state.renderer;
        const option = this.getOption();

        return <Chart renderer={renderer} option={option} />;
    }
    // getOption 这个函数主要用于配置 option,包括将数据配置进去
    // 也可以将其放在 state 中,然后通过 setState 更新
    getOption = () => {
        // 组装数据,返回配置 option
        const currentData = this.props.charts.heatmap;

        return {
            tooltip: {
                position: 'top'
            },
            grid: {
                containLabel: true
            },
            xAxis: {
                type: 'category',
                splitArea: {
                    show: true
                },
                boundaryGap: true
            },
            yAxis: {
                type: 'category',
                splitArea: {
                    show: true
                },
                boundaryGap: true
            },
            visualMap: {
                min: 0,
                max: 20,
                calculable: true,
                left: 'left',
                bottom: 'bottom',
                dimension: 2
            },
            dataset: {
                source: currentData
            },
            series: [
                {
                    name: '热力图',
                    type: 'heatmap',
                    emphasis: {
                        itemStyle: {
                            shadowBlur: 10,
                            shadowColor: 'rgba(0, 0, 0, 0.5)'
                        }
                    },
                    encode: {
                        x: 0,
                        y: 1
                    },
                    tooltip: {
                        formatter(params) {
                            const [x, y, value] = params.data;

                            return [
                                `x: ${x}`,
                                `y: ${y}`,
                                `value: ${value}`
                            ].join('<br/>');
                        }
                    }
                }
            ]
        };
    };
}

export default connect(
    state => ({ charts: state.charts }),
    dispatch => ({
        getChart: bindActionCreators(getChart, dispatch)
    })
)(HeatmapChart);

NO!!!

在这里,我使用echarts提供的模块化加载方式,实现了几个react-echarts图表组件:react-echarts图表在线渲染查看

你可以打开控制台,观察每个图表组件的加载情况。

但是,如果你认为仅仅是模块导入echarts的tooltip、grid这些插件就完事了,那么我也用不着写这篇文章分享了,下面会讲到另外一种异步加载方式。

导入echarts,最烦人的是什么?配置option是其一,其二就是极其庞大的echarts!特别是管理后台使用到echarts的时候,如果需要同个页面展示数十种图表类型,你就该好好考虑性能问题了。

插件版本号

  "echarts": "^3.6.2",
  "react": "^15.6.1",
  "react-dom": "^15.6.1"

实现了哪些图表组件

1、饼图
2、柱状图
3、折线图
4、散点图
5、地图
6、雷达图
7、k线图

我们不总是需要插件

实现这些echarts-react组件的目的,是告诉大家,react可以不需要引入第三方插件,使用echarts,不要惧怕react组件!

看过很多人说react难写,因为他们习惯了在jQuery开发模式下导入echarts、swiper、d3等插件。而突然切换到react中,就产生了不知所措的感觉。
如何在react中导入第三方插件,成为了他们心中的痛点,所以一些人就认为需要别人封装好的echarts-react插件或者其他react插件,才能使用,这种想法是错的。

echarts体积太大,使用模块化加载

以柱状图为例子,我们根据需要渲染的插件采取模块导入,不渲染的组件不导入,最大程度减小js。

import echarts from 'echarts/lib/echarts' //必须
import 'echarts/lib/component/tooltip'
import 'echarts/lib/component/grid'
import 'echarts/lib/chart/bar'

组件化开发的福音,react组件模块化加载

demo中采用单个echarts组件异步打包加载的模式,因为echarts组件普遍偏大,即使压缩也效果不明显,所以异步加载是最好的方式。

import { pieOption, barOption, lineOption, scatterOption, mapOption, radarOption, candlestickOption } from './optionConfig/options'
const PieReact = asyncComponent(() => import(/* webpackChunkName: "PieReact" */'./EchartsDemo/PieReact'))  //饼图组件
const BarReact = asyncComponent(() => import(/* webpackChunkName: "BarReact" */'./EchartsDemo/BarReact')) //柱状图组件
const LineReact = asyncComponent(() => import(/* webpackChunkName: "LineReact" */'./EchartsDemo/LineReact'))  //折线图组件
const ScatterReact = asyncComponent(() => import(/* webpackChunkName: "ScatterReact" */'./EchartsDemo/ScatterReact'))  //散点图组件
const MapReact = asyncComponent(() => import(/* webpackChunkName: "MapReact" */'./EchartsDemo/MapReact'))  //地图组件
const RadarReact = asyncComponent(() => import(/* webpackChunkName: "RadarReact" */'./EchartsDemo/RadarReact')) //雷达图组件
const CandlestickReact = asyncComponent(() => import(/* webpackChunkName: "CandlestickReact" */'./EchartsDemo/CandlestickReact')) //k线图组件

启动项目

//安装
npm install

//启动
npm start

打包项目

npm run build

实现方案介绍

1、每个图表单独封装成一个组件,通过参数传递数据,你会发现,图表内部代码几乎完全一样,只有import的类型不同。

2、异步加载是提高图表加载性能的最佳方式,不管是服务端还是客户端渲染。

3、在这些demo中,我认为对你来说最有价值的是react组件异步加载模式,很多人异步加载组件是通过拆分路由的方式,而非路由组件的异步加载,并不多人去尝试。但我想告诉你的是,
非路由组件的异步加载会将你的庞大的父组件拆分的更细,体积更小,加载的更加流畅。

方法一:

echarts-for-react 是一个非常简单的针对于 React 的 Echarts 封装插件。

和使用所有其他插件一样,首先,我们需要 install 它:

第一步:

npminstall --save echarts(依赖)

npminstall --save echarts-for-react

第二步:

在我们的项目中导入:

importReactEcharts from 'echarts-for-react'

第三步:

在 render 函数中使用:

  option={this.getOption}

  notMerge={true}

  lazyUpdate={true}

  style={{width: ‘400px’, height: ‘400px’}}

/>

组件基本参数介绍:

option:接收一个对象,该对象为 echarts 的配置项,详见:                 http://echarts.baidu.com/option.html#title

notMerge:可选,是否不跟之前设置的 option 进行合并,默认为 false,即合并。

LazyUpdate:可选,在设置完 option 后是否不立即更新图表,默认为 false,即立即更新。

style:echarts 容器 div 大小,默认:{height: ‘300px’}


方法二:

当然,我们也不是真的需要一个 react-echarts 插件,我们可以使用 echarts 提供的模块化加载方法,按需导入我们需要的图表:

首先,我们需要在项目中导入 echarts:

importecharts from 'echarts/lib/echarts'    //必须

import'echarts/lib/component/tooltip'        //图表提示框(按需)

import'echarts/lib/component/grid'      //图表网格(按需)

import 'echarts/lib/chart/bar'                 //引入柱状图(按需)

import'echarts/lib/chart/line’              //引入折线图(按需)

然后:我们需要在 render 函数中为图表放好一个容器:

{this.chartContainer = refs}} style={{width: ‘400px’, height: ‘400px’}}>

最后,我们需要在合适的生命周期中绘制我们的图表:

letmyChart = echarts.init(this.chartContainer)

letoption = {//echarts配置项}

myChart.setOption(option,true)


好了,echarts 已经成功的在项目中跑起来啦!


-END- 



  • 18
    点赞
  • 91
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值