文章目录
现在的前端ui框架越来越多,各个不同的ui框架有着自己明显的风格,而我们自己在开发时候难免会遇到一些框架不切合,或者需要定制化开发的情况。例如,我们之前写的一个前端项目,ui框架用的是 blueprint,facebook 的那一套。之后又写的一个项目用的是 antdesign ,蚂蚁金服的。
主要内容:
本文主要内容是记录一些自己在前端开发时遇到的一些需要造轮子的问题,记录分享。主要两点问题:一是blueprint框架提供的table组件可用性太差,于是自己手写了一个table组件;二是手动封装一个显示文本标签,解决表内容超出长度的问题。另外是分享一个写typescript在antd中踩的小坑。
一、commenTableList,自己封装的表格组件
blueprint 的ui画风更偏社交应用一些,而 antdesign 明显就是更适合用做数据报表,在数据展示,呈现。我们当时用的是 blueprint3.2.0 版本,可能因为blueprint更趋于社交应用的原因,它表格展示的table适配性很差,于是我在项目中自己重新封装了一个commenTableList组件用于项目中表格展示数据。代码如下:
import * as React from 'react';
import {Spinner,Text} from '@blueprintjs/core';
export interface IProps{
data:any[],
config:any[],
table_width:string,
loading:string,
}
export class TableList extends React.PureComponent<IProps,any>{
constructor(props:IProps){
super(props)
this.state = {
data:props.data,
config:props.config,
table_width:props.table_width,
loading:props.loading,
}
}
// 组件初始化时不调用,组件接受新的props时调用
public componentWillReceiveProps(nextProps:IProps){
this.setState({
data:nextProps.data,
config:nextProps.config,
table_width:nextProps.table_width,
loading:nextProps.loading,
});
}
public renderTable(data:any,config:any,tableWidth:string,loading:string){
let html:any = '';
if(loading === 'loading'){
html = <Spinner/>
}else if(loading === 'success'){
if(data.length<=0){
html = <div>当前暂时没有数据。</div>;
}else{
html= <table className="mytable" style={{width:tableWidth}}>
<thead>
<tr>
{
config.map(
(e:any)=>{
return(
// tslint:disable-next-line:jsx-key
<td style={{width:e.width}}>
{
e.label
}
</td>
)
}
)
}
</tr>
</thead>
<tbody>
{
data.map(
(ele:any)=>{
return(
// tslint:disable-next-line:jsx-key
<tr>
{
config.map(
(e:any)=>{
let r=<div/>
e.render!==undefined?
r=<td style={{width:e.width}}>
<div style={{width:'100%'}}>
<Text ellipsize={true} tagName='div'> {e.render(ele)} </Text>
</div>
</td>:
r=<td style={{width:e.width}}>
<div style={{width:'100%'}}>
<Text ellipsize={true} tagName='div'> {ele[e.key]} </Text>
</div>
</td>;
return(r)
}
)
}
</tr>)
})
}
</tbody>
</table>
}
}else if(loading === 'error'){
html = <div>当前暂时没有数据。</div>;
}
return html;
}
public render(){
const {data,config,table_width,loading} = this.state;
return (
<div style={{width:'100%',height:'100%'}}>
{this.renderTable(data,config,table_width,loading)}
</div>
)
}
}
使用时只需要向 TableList 组件中传入 config,table_width,和 data。其中 config 为 table 的配置项配置列名,数据的字段名,和该列宽度。 table_width为表的宽度。
。例如,我写了一个测试组件,效果如图:
其中传入的 config 为 table 如下:
public render() {
const config = [
{
key:'addressName',label:'轨迹名称',width:'20%'
},
{
key:'trailRemark',label:'轨迹描述',width:'20%'
},
{
key:'trailTime',label:'轨迹时间',width:'20%'
},
{
key:'Remark',label:'描述',width:'20%'
},
{
key:'Time',label:'时间',width:'20%'
},
]
const data = [
{
addressName : '111',
trailRemark : '111',
trailTime : '111',
Remark : '111',
Time : '111',
},
{
addressName : '222',
trailRemark : '222',
trailTime : '222',
Remark : '222',
Time : '222',
},
{
addressName : '333',
trailRemark : '333',
trailTime : '2333',
Remark : '333',
Time : '333',
},
{
addressName : '444',
trailRemark : '444',
trailTime : '444',
Remark : '444',
Time : '444',
},
{
addressName : '555',
trailRemark : '555',
trailTime : '555',
Remark : '555',
Time : '555',
},
]
return(
<TableList data={data} config={config} loading='success' table_width={'100%'}/>
);
基本上项目中各种需要表格形式展示的,都可以直接调用该组件。
二、antd的一些适配组件
在使用 antd 的 table 组件时,如果页面上表格样式不够大,或数据太长就会出现下面这种情况
页面无法正常展示,对此有几种解决方法,最简单的当然就是修改表的样式。但是在一些极端情况下这种方法会显得十分无力。因此我推荐自己封装一个文本标签组件用作适配 table 展示数据 —— text标签。
用该标签嵌套展示的文本内容,向其传入data和widths。data为文本内容,widths为标签宽度,当内容超过设定宽度时会自动省略,鼠标悬浮在上面可以查看省略的内容。效果图如下:
代码如下:
Text标签
import * as React from 'react';
export interface IProps{
data : string ,
widths : string,
}
export class Text extends React.PureComponent<IProps,any>{
constructor(props:any){
super(props);
this.state = {
data: this.props.data,
widths: this.props.widths,
}
}
public componentWillReceiveProps(nextProps:IProps){
this.setState({
data: nextProps.data,
widths: nextProps.widths,
});
}
public render() {
const {data,widths} = this.state;
return(
<div className="text-lable" style={{width : widths}} title={data}> {data} </div>
)
}
}
div,text-lable的样式
.text-lable{
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
word-wrap: normal;
}
text在table中的使用实例
在table渲染的时候回调。将具体内容传入text标签展示就能得到上图效果。table里的text标签具体使用实例如下:
<Table style={{ height: 600, width: 600 }}
dataSource={dataModal}
bordered={false}
columns={[
{
title: '实体ID',
dataIndex: 'entityID',
render: (text: any) => <Text widths="60px" data={text}/>
},
{
title: '出现地点',
dataIndex: 'entitySpace',
render: (text: any) => <Text widths="60px" data={text}/>
},
{
title: '出现时间',
dataIndex: 'entityTime',
render: (text: any) => <Text widths="60px" data={text}/>
},
{
title: '伴随ID',
dataIndex: 'accompanyID',
render: (text: any) => <Text widths="60px" data={text}/>
},
{
title: '出现地点',
dataIndex: 'accompanySpace',
render: (text: any) => <Text widths="60px" data={text}/>
},
{
title: '出现时间',
dataIndex: 'accompanyTime',
render: (text: any) => <Text widths="60px" data={text}/>
},
]}
pagination={{ // 分页
pageSize : 9,
}}
/>
关于andt的table在typescript中的一个小坑
主要关于antd,table的api中rowclassname属性回调函数的问题,也算是一个不大不小的坑,没有经验的话很容易才进去。
我是在写表的隔行变色的样式的时候遇到的。
如上图效果,思路是给回调的时候给各行一个classname,然后写自己想要的样式。antd 的官方api给的rowclassname回调函数如下,但是在typescript中直接这么写会 TSlint 报错。
一开始rowclassname是这么写的
rowClassName={(record, index) => {
let className = 'light-row';
if (index % 2 === 1) className = 'dark-row';
return className;
}
就官方api而言没什么问题,但在typescript中样写会报错,TSlint认为这种写法不符合它的可读性。刚开始写ts的小伙伴可能会找很久的原因。其实只需要再外面嵌套一层return就行。正确代码如下:
<Table
dataSource={dataList}
bordered={false}
columns={[
{
title: '实体ID',
dataIndex: 'entityID',
},
{
title: '匹配次数',
className: 'column-money',
},
{
title: '匹配度',
dataIndex: 'degree',
},
]}
rowClassName={this.rowName()}
/>
// rowName方法:
private rowName = () => {
return (record: any, index: number) => {
let className = 'light-row';
if (index % 2 === 1) {
className = 'dark-row'
};
return className;
}
}
css样式:
.light-row {
background: #ffffff;
}
.dark-row {
background: #f4f8ff;
}
这样写就能得到上述隔行变色的table样式。