【共享单车】—— React后台管理系统开发手记:AntD Table基础表格

react

前言:以下内容基于React全家桶+AntD实战课程的学习实践过程记录。最终成果github地址:https://github.com/66Web/react-antd-manager,欢迎star。


 一、基础表格

  • Table组件基础Api

  1. bordered属性:是否展示外边框和列边框
  2. columns属性:表格列的配置描述(即表头)
  3. dataSource属性:数据数组
  4. pagination属性:分页器,设为 false 时不展示和进行分页

     <Card title="基础表格">

    <Table

    bordered

    columns={columns}

    dataSource={this.state.dataSource}

    pagination={false}

    />

    </Card>

  • Table基本用法

  1. render()中:定义columns表头配置信息数组

     const columns = [

    {

    title: 'id', //表头标题

    dataIndex: 'id' //数据源

    },

    {

    title: '用户名',

    dataIndex: 'userName'

    },

    {

    title: '性别',

    dataIndex: 'sex',

    render(sex){

    return sex === 1 ? '男' : '女'

    }

    },

    {

    title: '状态',

    dataIndex: 'state',

    render(state){

    let config = {

    '1': '咸鱼一条',

    '2': '人民公仆',

    '3': '医院护士',

    '4': '科技公司FE',

    '5': '创业者'

    }

    return config[state]

    }

    },

    {

    title: '爱好',

    dataIndex: 'interest',

    render(abc){

    let config = {

    '1': '游泳',

    '2': '打篮球',

    '3': '踢足球',

    '4': '跑步',

    '5': '爬山',

    '6': '骑行',

    '7': '桌球',

    '8': '麦霸'

    }

    return config[abc]

    }

    },

    {

    title: '生日',

    dataIndex: 'birthday'

    },

    {

    title: '地址',

    dataIndex: 'address'

    },

    {

    title: '早起时间',

    dataIndex: 'time'

    }

    ]

  2. componentDidMount()中:指定表格的数据源 dataSource 为一个数组

    const dataSource = [   //数据源

    {

    id: '0',

    userName: 'Elena',

    sex: '1',

    state: '1',

    interest: '1',

    birthday: '2019-01-01',

    address: '西虹市海淀区桃花公园',

    time: '07:00'

    },

    {

    id: '1',

    userName: 'Mary',

    sex: '1',

    state: '2',

    interest: '3',

    birthday: '2019-01-01',

    address: '西虹市海淀区桃花公园',

    time: '07:00'

    },

    {

    id: '2',

    userName: 'Tom',

    sex: '2',

    state: '3',

    interest: '4',

    birthday: '2019-01-01',

    address: '西虹市海淀区桃花公园',

    time: '07:00'

    }

    ]  

  3. 报错:原因是数据需要指定唯一key值;使用 map 循环遍历可以快速添加key值

      

  4. 注意:定义好数据源后,必须通过this.setState将dataSource添加到state中

    state={}

    componentDidMount(){

    const dataSource= [……],

    dataSource.map((item, index) => {

    item.key = index;

    })

    this.setState({

    dataSource

    })

    }

         

二、动态数据渲染表格

  • 动态渲染数据

  1. 在线工具模拟数据:Easy Mock用法及Mock.js规范 

  2. 生成数据

  3. src->axios->index.js:定义ajax方法,封装axios异步获取Easy Mock项目虚拟数据的过程【项目工程化】

    import axios from 'axios'

    import { Modal } from 'antd';

    export default class Axios{

    ……

    static ajax(options){

    let baseApi = 'https://www.easy-mock.com/mock/5c2c7c1b580d6209d1e2aa88/mockapi'

    return new Promise((resolve,reject) => {

    axios({

    url: options.url,

    method:'get',

    baseURL: baseApi,

    timeout: 5000,

    params: (options.data && options.data.params) || ''

    }).then((response)=>{

    if(response.status === 200){

    let res = response.data;

    if(res.code === 0){

    resolve(res);

    }else{

    Modal.info({

    title: '提示',

    content: res.msg

    })

    }

    }else{

    reject(response.data)

    }

    })

    });

    }

    注意:根据返回的response获取数据信息时,要按照Easy Mock中定义的数据结构而定!!!

  4. baseTable.js中:定义request方法,调用axios动态获取Mock数据

    import axios from './../../axios/index'

    state = {

    dataSource2: []

    }

    params = {

    page: 1

    }

    //动态获取mock数据

    request = () => {

    let _this = this;

    axios.ajax({

    url: '/table/list',

    data:{

    params:{

    page: this.params.page

    }

    }

    }).then((res) => {

    if(res.code === 0){

    res.list.map((item, index) => {

    item.key = index

    })

    this.setState({

    dataSource2: res.list

    })

    }

    })

    }

  5. Table组件中:指定数据源为动态获取到的dataSource2

    <Card title="Mock-动态数据渲染表格" style={{margin: '10px 0'}}>

    <Table

    bordered

    columns={columns}

    dataSource={this.state.dataSource2}

    pagination={false}

    />

    </Card>

  

三、表格单选

  • rowSelection属性:列表项是否可选择,对象
  • 配置项:

  1. type:单选/多选
  2. selectedRowKeys:指定选中项的key数组,需要和onChange进行配合(单选,仅onRow事件即可)

    const selectedRowKeys = this.state.selectedRowKeys;

    const rowSelection = {

    type: 'radio',

    selectedRowKeys

    }

  • onRow事件:控制点击某一行,设置行属性

     <Card title="Mock-单选" style={{margin: '10px 0'}}>

    <Table

    bordered

    rowSelection={rowSelection}

    onRow={(record, index) => {

    return {

    onClick: () => {

    this.onRowClick(record, index)

    } //点击行

    }

    }}

    columns={columns}

    dataSource={this.state.dataSource2}

    pagination={false}

    />

    </Card>

    提取出onRowClick方法:获取当前点击行的数据项record和索引index

    //点击某一行 record:当前点击行的数据项 index:当前点击行的索引

    onRowClick = (record, index) => {

    let selectKey = [index];

    Modal.info({

    title: '信息',

    content: `用户名:${record.userName},用户爱好:${record.interest}`

    });

    this.setState({

    selectedRowKeys: selectKey,

    selectedItem: record

    })

    }

      

四、表格复选

  • 配置rowSelection属性对象

  1. 添加onChange事件
  2. selectedRowKeys:当前选中的行索引
  3. selectedRows:当前选中的行对象

    const rowCheckSelection = {

    type: 'checkbox',

    selectedRowKeys,

    onChange: (selectedRowKeys, selectedRows) => {

    // let ids = []

    // selectedRows.map((item) => {

    // ids.push(item.id)

    // })

    this.setState({

    selectedRowKeys, //必需

    // selectedIds: ids,

    selectedRows

    })

    }

    }

  • 选中多行执行操作

  1. 获取state中的seletedRows对象,遍历得到item对象

  2. 利用item.id执行操作
  3. 执行完操作,需要重新刷新页面:调用this.request()

    //多选执行删除动作

    handleDelete = () => {

    let rows = this.state.selectedRows;

    let ids = [];

    rows.map((item) => {

    ids.push(item.id)

    })

    Modal.confirm({

    title: '删除提示',

    content: `您确定要删除这些数据吗?${ids.join(',')}`,

    onOk: () => {

    message.success('删除成功')

    this.request(); //重新刷新页面

    }

    })

    }

  4. request方法中:当获取数据成功后,重置state中当前选中项参数均为空

    selectedRowKeys: [], //重置

    selectedRows: null,

  • 其它,同单选

    <Card title="Mock-复选" style={{margin: '10px 0'}}>

    <div style={{marginBottom: 10}}>

    <Button onClick={this.handleDelete}>删除</Button>

    </div>

    <Table

    bordered

    rowSelection={rowCheckSelection}

    onRow={(record, index) => {

    return {

    onClick: () => {

    this.onRowClick(record, index)

    } //点击行

    }

    }}

    columns={columns}

    dataSource={this.state.dataSource2}

    pagination={false}

    />

    </Card>

      

五、表格分页

  •  src->utils->utils.js:封装pagination分页工具函数 【项目工程化】

    pagination(data,callback){

    return {

    onChange: (current) => {

    callback(current) //回调函数返回当前页

    },

    current: data.page,

    pageSize: data.page_size,

    total: data.total,

    showTotal: () => {

    return `共${data.total}条`

    },

    showQuickJumper: true //是否快速跳转至某一页

    }

    }  

    注意:获取data对象的数据,需要符合Easy Mock中模拟数据的数据结构!!!

  • request方法中:当获取数据成功后,调用Utils.pagination()给state添加并配置pagination

    import Utils from './../../utils/utils'

    let _this = this; //保留外层this,否则this指向会有问题

    pagination: Utils.pagination(res,(current) => {

    _this.params.page = current;

    this.request();

    })

  • Table组件中使用pagination属性

    <Card title="Mock-表格分页" style={{margin: '10px 0'}}>

    <Table

    bordered

    columns={columns}

    dataSource={this.state.dataSource2}

    pagination={this.state.pagination}

    />

    </Card>

     

六、Loading拦截加载项

  •  index.html中:在<div >配置全局html文件 【项目工程化】

    <div class="ajax-loading" >

    <div class="overlay"></div>

    <div class="loading">

    <img src="https://media.number-7.cn/ebike-h5/static/images/common/loading.gif" alt="">

    <span>加载中,请稍后...</span>

    </div>

    </div>

  • src->style->loading.less:同时 common.less中引入

    /** load **/

    .ajax-loading{

    display: none;

    .loading{

    position: fixed;

    top: 50%;

    left: 50%;

    transform: translate(-50%,-50%);

    padding:0 40px;

    height: 80px;

    line-height: 80px;

    background: rgba(0, 0, 0, 0.75);

    border-radius: 6px;

    text-align: center;

    z-index: 9999;

    font-size:@fontD;

    color:#fff;

    img{

    width: 32px;

    vertical-align: middle;

    }

    span{

    margin-left:12px;

    }

    }

    .overlay{

    position: fixed;

    left: 0;

    right: 0;

    top: 0;

    bottom: 0;

    z-index: 9998;

    background: rgb(255, 255, 255);

    opacity: 0.1;

    }

    }

    @import './../style/loading.less';

  • src->axios->index.js:ajax方法中设置loading默认display block,当获取数据成功后,改为display none

    let loading;

    if(options.data && options.data.isShowLoading !== false){

    loading = document.getElementById('ajaxLoading');

    loading.style.display = 'block';

    }

    //其它代码

    .then((response)=>{

    if(options.data && options.data.isShowLoading !== false){

    loading = document.getElementById('ajaxLoading');

    loading.style.display = 'none';

    }

      

七、实例代码

  • pages->table->basicTable.js:对应路由/admin/table/basic

import React from 'react';

import {Card, Table, Modal, Button, message} from 'antd';

import axios from './../../axios/index'

import Utils from './../../utils/utils'

export default class BasicTables extends React.Component{

state = {

dataSource2: []

}

params = {

page: 1

}

componentDidMount(){

const dataSource = [ //数据源

{

id: '0',

userName: 'Elena',

sex: '1',

state: '1',

interest: '1',

birthday: '2019-01-01',

address: '西虹市海淀区桃花公园',

time: '07:00'

},

{

id: '1',

userName: 'Mary',

sex: '1',

state: '2',

interest: '3',

birthday: '2019-01-01',

address: '西虹市海淀区桃花公园',

time: '07:00'

},

{

id: '2',

userName: 'Tom',

sex: '2',

state: '3',

interest: '4',

birthday: '2019-01-01',

address: '西虹市海淀区桃花公园',

time: '07:00'

}

]

dataSource.map((item, index) => {

item.key = index;

})

this.setState({

dataSource

})

this.request();

}

//动态获取mock数据

request = () => {

let _this = this;

axios.ajax({

url: '/table/list',

data:{

params:{

page: this.params.page

},

// isShowLoading: false

}

}).then((res) => {

if(res.code === 0){

res.list.map((item, index) => {

item.key = index

})

this.setState({

dataSource2: res.list,

selectedRowKeys: [], //重置

selectedRows: null,

pagination: Utils.pagination(res,(current) => {

_this.params.page = current;

this.request();

})

})

}

})

}

onRowClick = (record, index) => {

let selectKey = [index];

Modal.info({

title: '信息',

content: `用户名:${record.userName},用户爱好:${record.interest}`

});

this.setState({

selectedRowKeys: selectKey,

selectedItem: record

})

}

// add = () => {

// let item = this.state.selectedItem;

// if(item.id){

// }

// }

//多选执行删除动作

handleDelete = () => {

let rows = this.state.selectedRows;

let ids = [];

rows.map((item) => {

ids.push(item.id)

})

Modal.confirm({

title: '删除提示',

content: `您确定要删除这些数据吗?${ids.join(',')}`,

onOk: () => {

message.success('删除成功')

this.request(); //重新刷新页面

}

})

}

render(){

const columns = [

{

title: 'id', //表头标题

dataIndex: 'id' //数据源

},

{

title: '用户名',

dataIndex: 'userName'

},

{

title: '性别',

dataIndex: 'sex',

render(sex){

return sex === 1 ? '男' : '女'

}

},

{

title: '状态',

dataIndex: 'state',

render(state){

let config = {

'1': '咸鱼一条',

'2': '人民公仆',

'3': '医院护士',

'4': '科技公司FE',

'5': '创业者'

}

return config[state]

}

},

{

title: '爱好',

dataIndex: 'interest',

render(abc){

let config = {

'1': '游泳',

'2': '打篮球',

'3': '踢足球',

'4': '跑步',

'5': '爬山',

'6': '骑行',

'7': '桌球',

'8': '麦霸'

}

return config[abc]

}

},

{

title: '生日',

dataIndex: 'birthday'

},

{

title: '地址',

dataIndex: 'address'

},

{

title: '早起时间',

dataIndex: 'time'

}

]

const selectedRowKeys = this.state.selectedRowKeys;

const rowSelection = {

type: 'radio',

selectedRowKeys

}

const rowCheckSelection = {

type: 'checkbox',

selectedRowKeys,

onChange: (selectedRowKeys, selectedRows) => {

// let ids = []

// selectedRows.map((item) => {

// ids.push(item.id)

// })

this.setState({

selectedRowKeys, //必需

// selectedIds: ids,

selectedRows

})

}

}

return (

<div>

<Card title="基础表格">

<Table

bordered

columns={columns}

dataSource={this.state.dataSource}

pagination={false}

/>

</Card>

<Card title="Mock-动态数据渲染表格" style={{margin: '10px 0'}}>

<Table

bordered

columns={columns}

dataSource={this.state.dataSource2}

pagination={false}

/>

</Card>

<Card title="Mock-单选" style={{margin: '10px 0'}}>

<Table

bordered

rowSelection={rowSelection}

onRow={(record, index) => {

return {

onClick: () => {

this.onRowClick(record, index)

} //点击行

}

}}

columns={columns}

dataSource={this.state.dataSource2}

pagination={false}

/>

</Card>

<Card title="Mock-复选" style={{margin: '10px 0'}}>

<div style={{marginBottom: 10}}>

<Button onClick={this.handleDelete}>删除</Button>

</div>

<Table

bordered

rowSelection={rowCheckSelection}

onRow={(record, index) => {

return {

onClick: () => {

this.onRowClick(record, index)

} //点击行

}

}}

columns={columns}

dataSource={this.state.dataSource2}

pagination={false}

/>

</Card>

<Card title="Mock-表格分页" style={{margin: '10px 0'}}>

<Table

bordered

columns={columns}

dataSource={this.state.dataSource2}

pagination={this.state.pagination}

/>

</Card>

</div>

)

}

}  


注:项目来自慕课网

以上是 【共享单车】—— React后台管理系统开发手记:AntD Table基础表格 的全部内容, 来源链接: utcz.com/z/382486.html

回到顶部