代码改变世界

【react表格组件】material-table 基本用法 & 组件override

2019-03-08 14:45  ZealouSnesS  阅读(6549)  评论(0编辑  收藏  举报

教程:

https://mbrn.github.io/material-table/#/

https://material-ui.com/api/table/

github:

https://github.com/mbrn/material-table

 

material-table是使用material-ui实现的react表格组件

 

1、基本使用方法:在react项目中导入该组件直接使用

安装

npm install material-table --save

使用

import MaterialTable from 'material-table'

class APP extends Component{
    render(){
        return (
        <div>
             <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"></link>  注意,这个标签必须在<MaterialTable>标签旁引用
            <MaterialTable>
            ...
            </MaterialTable>
        </div>
        );
    }
}

具体使用见:

https://www.npmjs.com/package/material-table

https://mbrn.github.io/material-table/#/

 

2、override组件

想要override material-table组件起因是因为material-table自带的toobar和checkbox是红色,并且没有提供修改这个样式的接口,而我想要改成蓝色。

方法就是首先到github上clone下来material-table源码:

https://github.com/mbrn/material-table

阅读material-table源码,发现material-table的实现原理是 MaterialTable类里面调用了MTableToolbar,MTableHeader,MTableBodyRow等类。

因此我们要修改material-table里的toobar和每一行的checkbox的话,所要做的工作:

首先就是继承MTableHeader、MTableBodyRow实现自己的MyMTableHeader、MyMTableBodyRow类,以实现MTableHeader、MTableBodyRow中checkbox颜色的修改;然后继承MaterialTable类实现自己的MyMaterialTable类;并在MyMaterialTable类中调用MTableToolbar、MyMTableHeader、MyMTableBodyRow类,如下黄底色部分:

(注:没有重写MTableToolbar是因为MTableToolbar使用了css in js,不需要override MTableToolbar就可以改变它的颜色,具体介绍见下面)

import React, { Component } from 'react';



import { withStyles } from '@material-ui/core/styles';
import MaterialTable from 'material-table';
import MTableToolbar from 'material-table/dist/m-table-toolbar';

import blue from '@material-ui/core/colors/blue';
import { createMuiTheme, MuiThemeProvider } from '@material-ui/core/styles'
import { Checkbox, TableCell } from '@material-ui/core';
import MTableBodyRow from 'material-table/dist/m-table-body-row';
import MTableHeader from 'material-table/dist/m-table-header';


https://material-ui.com/customization/themes/



const myTheme = createMuiTheme({
    palette: {
        secondary:{
            main: '#017FCB',
            // main: blue[400],
            // light: blue[400],
        },
    },
    typography:{
        useNextVariants: true,
    },
});


// override MTableBodyRow to change the color of tablebody_checkbox
class MyMTableBodyRow extends MTableBodyRow{
    renderSelectionColumn() {
        return (
          <TableCell padding="none" key="key-selection-column" style={{ width: 48 }}>
            {/* use  createMuiTheme & MuiThemeProvider to change the style of tablebody_checkbox */}
            <MuiThemeProvider theme={myTheme}>
                <Checkbox
                checked={this.props.data.tableData.checked === true}
                onClick={(e) => e.stopPropagation()}
                value={this.props.data.tableData.id.toString()}
                onChange={(event) => this.props.onRowSelected(event, this.props.path)}
                style={{
                    paddingLeft: 12 + this.props.level * 20,
                }}
                />
            </MuiThemeProvider>
          </TableCell>
        );
      }
}

class MyTableHeader extends MTableHeader{
    renderSelectionHeader() {
        return (
          <TableCell
            padding="none"
            key="key-selection-column"
            style={this.props.headerStyle}
          >
          {/* use  createMuiTheme & MuiThemeProvider to change the style of tableheader_checkbox */}
            <MuiThemeProvider theme={myTheme}>
                <Checkbox
                indeterminate={this.props.selectedCount > 0 && this.props.selectedCount < this.props.dataCount}
                checked={this.props.selectedCount === this.props.dataCount}
                onChange={(event, checked) => this.props.onAllSelected && this.props.onAllSelected(checked)}
                />
            </MuiThemeProvider>
          </TableCell>
        );
      }
}

// override MaterialTable to change toolbar & tablebody_checkbox & tableheader_checkbox
class MyMaterialTable extends MaterialTable{
    getProps(props){
        const calculatedProps=super.getProps(props);
        // use css in js to change style of toolbar
        // change the calculatedProps.components.Toolbar in MaterialTable.
        // read the source code of material-table to get the variable name to change
        calculatedProps.components.Toolbar=withStyles(styles)(MTableToolbar);
        calculatedProps.components.Row=MyMTableBodyRow;
        calculatedProps.components.Header=MyTableHeader;
        return calculatedProps;
    }
}

// change the background color of toolbar
const styles = theme => ({
    root: {
      paddingRight: theme.spacing.unit
    },
    highlight:
      theme.palette.type === 'light'
        ? {
          color: theme.palette.secondary.main,
        //   backgroundColor: blue[100],
          backgroundColor: '#98D3F2',
        }
        : {
          color: theme.palette.text.primary,
          backgroundColor: theme.palette.secondary.dark
        },
    spacer: {
      flex: '1 1 10%'
    },
    actions: {
      color: theme.palette.text.secondary,
    },
    title: {
      flex: '0 0 auto'
    },
    searchField: {
      paddingLeft: theme.spacing.unit * 2
    }
  });

export default MyMaterialTable;

 

 对于继承MTableHeader和MTableBodyRow并修改其中的checkbox的样式,我们采用material-ui提供的theme进行修改:

theme使用教程:

https://material-ui.com/customization/themes/

theme使用实例:

 

 对于不继承MTableToolbar,直接在MaterialTable中调用MTableToolbar时指定修改MTableToolbar的样式,我们使用css in js,见上面红字部分

个人认为通过withStyles()函数实现的css in js的优点:可以在子组件外部对子组件样式进行修改

css in js 优缺点:

看了这些框架后,可以发现CSS-in-JS的优势还是挺多的:

  • 因为有了生成的唯一class名称,避免了全局污染的问题
  • 唯一的class名称也解决了命名规则混乱的问题
  • JavaScript和CSS之间可以变量共享,比如一些基础的颜色和尺寸,这样再当需要在JavaScript里计算一些高度的时候,可以取到和dom相关的一些padding,margin数值,统一管理
  • 只生成页面需要用到的代码,缩减了最终包的大小,提升了性能
  • CSS的单元测试增加了样式重构的安全性

但是CSS-in-JS也存在着一些不足和争议:

  • 有些观点觉得JS和CSS的关系没这么近,把CSS写进JS里引入了新的一套依赖,增加了复杂度,新人加入项目后需要学习的东西就更多了,也让学习曲线更加陡了
  • 对前端框架确实有些依赖性,更适合于组件化的框架,如React等
  • Debug的时候需要花更多的功夫才能找到对应的样式代码
  • 覆盖第三方插件样式时会有权重不够的问题
  • Lint工具对于JavaScript内部的CSS代码样式支持的还不够
作者:ThoughtWorks中国
链接:https://www.jianshu.com/p/cefd3ae73255
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

 

 

 注意调用父类方法的语法:

调用父类构造方法:

super();

调用父类一般方法:

super.fatherfunc();

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

(另推荐一个组件 docz)