动态渲染可编辑单元格的Table

 

     一、问题描述

          问题是这样的,后台传了xArr = [x1, x2,...,xn]和yArr = [y1, y2, ..yn]两个数组,前端要渲染出表格并且可以填写每个单元格的值,然后按照一定数据结构保存并传给后台,并且再次获取这个数据结构和数组xArr、yArr可以自己渲染出这个表?实现新增和修改的功能。大致界面效果如下图所示:

y1, y2,...,yn作为列名,x1,x2, ..., xn作为第一列数据,此业务模型是一种常见的表格,只不过要求行列都不固定,由后台数据提供并且动态生成。还要能够实现修改功能。本质上是一个动态渲染可编辑Table的问题。难点在于动态构建表格并且实现数据展示和保存。

 

二、解决思路

      (1)数据转换成表格后,处理起来就简单了,如果以常见的Table组件为例,只需要构建columns和dataSource两个数组数据即可渲染出表格;

      (2)渲染出表格后,表格每一个余下的单元格都要可输入,可以考虑单元格利用render渲染出Input组件,通过Input的操作onChange或onBlur去改变数据并存储。

      (3)数组是引用类型,可以利用引用类型只要没有深拷贝或改变指针指向内存地址就不变的原理,方便记录操作后的数据。

 

三、解决方法(以React结合ant design UI的Table组件为例):

       (1)动态构建columns(表格列数据)和dataSource(表格数据源)渲染出表格。(Table可参考 https://ant.design/components/table-cn/#header)

 1 const xArr = ['x1', 'x2', 'x3', 'x4'];
 2 const dataSource = xArr.map((v, i) => ({
 3      key: String(i),//此处自定义表格每一行的唯一key,如果没有设置唯一标志会报错
 4      y0: v,//第一列数据即显示X1-Xn的那一列
 5 }));
 6 
 7 const yArr = ['y1', 'y2', 'y3', 'y4', 'Y5'];
 8 const columns = [{
 9     title: ' ',
10     dataIndex: 'y0',//第一列y0为列的dataIndex,用于显示x1-xn
11 }, ...yArr.map(item => ({//其他列通过yArr循环得到,并用...解构直接合并为columns
12     title: item,
13     dataIndex: item,
14 }))];

这样就得到形如dataSource = [{ key: '0', y0:'x1'}, { key: '0', y0:'x1'},...];  columns = [{ title: '', dataIndex: 'y0'},{ title: 'y1', dataIndex: 'y1'},...];的表格数据,将此数据源传入表格组件Table,即可渲染出表格如下:

<Table columns={columns} dataSource={dataSource} />

(2)表格添加Input并且根据onChange/onBlur事件动态记录dataSource的变化。

 1 const columns = [{
 2       title: ' ',
 3       dataIndex: 'y0',
 4     }, ...yArr.map(item => ({
 5       title: item,
 6       dataIndex: item,
 7       render: (text, record) => (
 8         <Input defaultValue={record[item]} onChange={(e) => { record[item] = e.target.value; }} />
 9       ),
10     }))];

渲染效果如下:

四、完整代码

/**
 * @author  xiao-pengyou
 * @create date 2019-03-27
 * @desc 动态可编辑表格
* */

import React, { PureComponent } from 'react';
import { Table, Input } from 'antd';

export default class Demo extends PureComponent {
  state = { dataSource: [] };

  componentDidMount() {
    const xArr = ['x1', 'x2', 'x3', 'x4'];
    const dataSource = xArr.map((v, i) => ({key: String(i),y0: v}));
    this.setState({ dataSource });//dataSource不能在render里面构建,在render里面构建每次重新渲染的时候dataSource会被重新构建,指针指向变化导致先前的修改不能被跟踪
  }

  render() {
    const yArr = ['y1', 'y2', 'y3', 'y4', 'y5'];
    const that = this;//定义中间量that=this确保columns内部onChange事件作用域为当前组件,方便调用forceUpdate()强制渲染表格
    const columns = [{
      title: ' ',
      dataIndex: 'y0',
    }, ...yArr.map(item => ({
      title: item,
      dataIndex: item,
      render: (text, record) => (
        <Input value={record[item]} onChange={(e) => { record[item] = e.target.value; that.forceUpdate(); }} />
      ),
    }))];//最终的dataSource就是我们想要的数据结构,修改时直接把这个dataSource传给构建的表格就可以渲染
    return <Table columns={columns} dataSource={this.state.dataSource} bordered pagination={false} />;//bordered设置边框,pagination=false取消分页功能,可以不用在意此参数
  }
}

  最终效果(控制台输出为提交给后台的dataSource数组):

以上就是一个动态列的可编辑表格的React实现方式。如有问题欢迎留言批评指正,谢谢!

 本文为原创博客,非法抄袭或复制将追究法律责任,转载请注明出处:https://www.cnblogs.com/xiao-pengyou/

 

转载于:https://www.cnblogs.com/xiao-pengyou/p/10605011.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
el-table是一个基于element-ui的表格组件。编辑单元格的操作需要使用到el-table的slot和scoped-slot属性。 首先,在el-table中定义一个slot,用来渲染需要编辑单元格。例如,可以在表格的第二列中添加一个可编辑单元格: ```html <el-table-column label="姓名"> <template slot-scope="scope"> <span>{{ scope.row.name }}</span> </template> </el-table-column> <el-table-column label="年龄"> <template slot-scope="scope"> <span class="editable-cell">{{ scope.row.age }}</span> </template> </el-table-column> ``` 在第二列中,我们使用了一个class为editable-cell的span元素来渲染需要编辑单元格。 接下来,我们需要定义一个scoped-slot,用来渲染编辑单元格时的弹出框。例如,我们可以使用el-dialog组件来实现弹出框的效果: ```html <el-table-column label="年龄"> <template slot-scope="scope"> <span class="editable-cell" @click="editCell(scope.row, 'age')">{{ scope.row.age }}</span> <el-dialog :visible.sync="dialogVisible"> <el-input v-model="editValue"></el-input> <div slot="footer"> <el-button @click="dialogVisible = false">取消</el-button> <el-button type="primary" @click="saveEdit()">保存</el-button> </div> </el-dialog> </template> </el-table-column> ``` 在这里,我们为editable-cell元素添加了一个@click事件,当单元格被点击时,会触发editCell方法。该方法会设置dialogVisible为true,显示el-dialog组件。el-dialog中包含一个el-input用来输入编辑后的值,以及一个保存和取消按钮。 在methods中定义editCell、saveEdit方法: ```js methods: { editCell(row, prop) { this.editRow = row this.editProp = prop this.editValue = row[prop] this.dialogVisible = true }, saveEdit() { this.dialogVisible = false this.editRow[this.editProp] = this.editValue } } ``` 在editCell方法中,我们记录当前需要编辑的行和属性,以及设置编辑框的值和可见性。在saveEdit方法中,我们将编辑后的值保存到数据源中,并将编辑框隐藏。 最后,为了让用户知道哪些单元格可以编辑,我们可以使用CSS样式来为编辑单元格添加一个边框或者背景色: ```css .editable-cell { cursor: pointer; border: 1px dashed #ccc; padding: 2px 6px; display: inline-block; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值