封装react的echarts组件(根据窗口或者父级容器的变化自适应图表大小)
echarts 组件:
import React, { Component } from 'react'; import echart from 'echarts'; import { Consumer } from "@/layouts/components/default_layout/default_layout"; // 引入父组件的Consumer容器 class Bar extends Component { constructor(props) { super(props); this.chartRef = React.createRef(); } chartRef; chart; componentDidUpdate() {
// 数据更新时,重绘图表 this.init() } componentDidMount() { this.init() } init() { // 基于准备好的dom,初始化echart实例 this.chart = echart.init(this.chartRef.current); // 绘制图表 this.chart.setOption({ // title: { // text: 'echart 入门示例' // }, grid: { top: 55, bottom: 58, left: 124, right: 46 }, tooltip: {}, xAxis: { axisLine: { lineStyle: { color: '#E8E9F6' } }, axisTick: { show: false }, splitLine: { show: false }, axisLabel: { color: '#383874', margin: 15, fontSize: 14 }, data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'] }, yAxis: { axisTick: { show: false }, splitLine: { show: false }, axisLine: { lineStyle: { color: '#E8E9F6' } }, axisLabel: { color: '#383874', margin: 20, fontSize: 14 }, }, series: [{ name: '销量', type: 'bar', barWidth: 20, itemStyle: { color: '#0087FF', barBorderRadius: [10, 10, 0, 0], }, data: [5, 20, 36, 10, 10, 20] }] });
// 这里是为了让echarts图表随着浏览器的可视区域变化自适应 参照图3,图4的区别(在不刷新页面的情况下) window.addEventListener("resize", () => { let p_width = document.body.clientWidth - this.lastWidth; this.chart.resize({ width: p_width }); }); } resize() { let p_width = document.body.clientWidth - this.lastWidth; if (this.chart) this.chart.resize({ width: p_width }); } lastWidth; render() { return (<Consumer> {(obj) => {
// 下面三行代码是为了实现下图1、2的效果,在二级菜单收起展开时,让echarts随着父级的宽度变化自适应(在不刷新页面的情况下) let p_width = document.body.clientWidth; this.lastWidth = obj.width; obj.onChange(this.resize.bind(this)); return <div ref={this.chartRef} style={{ width: `calc(${p_width}px - ${obj.width}px)`, height: '100%' }}></div> }} </Consumer>) } } export default Bar;
父组件:
import React, { Component } from 'react'; import { connect } from 'dva'; import Bar from '../components/bar'; class Index extends Component { render() { return (<Bar />) } } export default connect()(Index);
default_layout:(涉及到context的应用<Provider和Consumer>)
import React from 'react'; import { connect } from 'dva'; const width = document.body.clientWidth - 80; export const { Provider, Consumer } = React.createContext({ width: width }); class BasicLayout extends React.Component {
constructor(props) {
super(props);
this.state = {
collapsed: false
}
}
onCollapse(collapsed) {
this.setState({
collapsed: collapsed
}, () => {
this.fn()
})
}
fn = () => { }
render() { return (<>
<Menu collapsed={this.state.collapsed} onCollapse={this.onCollapse.bind(this)} />
<Provider value={{ width: (this.state.collapsed ? 250 : 100) + 80, onChange: (fn) => this.fn = fn }}> <div className={styles.content_inner}> {this.props.children} </div> </Provider>
</>) } }
export default connect()(<BasicLayout />);
图1:
图2:
图3:(浏览器窗口最大化)
图4:(浏览器窗口缩小后)