ant design vue嵌套表格及表格内部编辑的用法说明


Posted in Javascript onOctober 28, 2020

实现效果:

ant design vue嵌套表格及表格内部编辑的用法说明

因为pro手脚架中封装的s-table不支持expand和expandedRowsChange事件,无法实现根据展开节点获取其内部数据的需求,因此直接使用a-table组件

表格外层可以翻页,查询携带页码参数

<a-table
size="default"
rowKey="dict_id" //根据自己数据内部关键针设定
ref="table"
@expandedRowsChange="expandedRowsChange"
@expand="expand" // 展开表格节点操作
@change="change" // 外层表格中排序,翻页,修改页面数量等操作
:expandedRowKeys="expandedRowKeys" // 操作展开的节点
:pagination="pagination" // 页码参数
:columns="columns" // 表头
:dataSource="loadData" // 数据
>
<a-table
size="default"
style="margin-bottom:0;"
rowKey="key"
slot="expandedRowRender" // 以内层方式展现
:columns="innerColumns"
:dataSource="data"
:pagination="false"
:loading="innerloading"
@change="innerhandleChange"
>
<template v-for="(col, i) in ['item_text', 'item_value', 'item_checked', 'item_remark', 'item_sort', 'item_status']" :slot="col" slot-scope="text, record">
<a-input
:key="col"
v-if="record.editable"
style="margin: -5px 0"
:value="text"
:placeholder="innerColumns[i].title"
@change="e => handleChange(e.target.value, record.key, col)"
/>
<template v-else>{{ text }}</template>
</template> // 内部表格可编辑模板
<template slot="operation" slot-scope="text, record">
<template v-if="record.editable">
<span v-if="record.isNew">
<a @click="saveRow(record)">添加</a>
<a-divider type="vertical" />
<a-popconfirm title="是否要删除此行?" @confirm="remove(record.key)">
<a>删除</a>
</a-popconfirm>
</span>
<span v-else>
<a @click="saveRow(record)">保存</a>
<!-- <a-divider type="vertical" />
<a @click="cancel(record.key)">取消</a> -->
</span>
</template> // 内部表格新增模板
<span v-else>
<a @click="toggle(record)">编辑</a>
</span>
</template>
</a-table>
<div
slot="expandedRowRender"
style="margin: 0">
<a-button style="width: 100%; margin-top: 16px; margin-bottom: 8px" type="dashed" icon="plus" @click="newMember">新增属性</a-button>
</div>
<span slot="action" slot-scope="text, record">
<a @click="handleEdit(record)">编辑</a>
</span>
</a-table>

主要数据:

expandedRowKeys: [],
  // 表头
  columns: [
  {
   title: '字典编码',
   dataIndex: 'dict_code'
  },
  {
   title: '字典名称',
   dataIndex: 'dict_name'
  },
  {
   title: '状态',
   dataIndex: 'dict_status'
  },
  {
   title: '字典描述',
   dataIndex: 'dict_remark'
  }, {
   title: '操作',
   width: '150px',
   dataIndex: 'action',
   scopedSlots: { customRender: 'action' }
  }
  ],
  loadData: [],
  innerColumns: [
  {
   title: '字段名',
   dataIndex: 'item_text',
   key: 'item_text',
   width: '15%',
   scopedSlots: { customRender: 'item_text' }
  },
  {
   title: '字段值',
   dataIndex: 'item_value',
   key: 'item_value',
   width: '15%',
   scopedSlots: { customRender: 'item_value' }
  },
  {
   title: '默认选中(0:否,1:是)',
   dataIndex: 'item_checked',
   key: 'item_checked',
   width: '10%',
   scopedSlots: { customRender: 'item_checked' }
  },
  {
   title: '备注',
   dataIndex: 'item_remark',
   key: 'item_remark',
   width: '20%',
   scopedSlots: { customRender: 'item_remark' }
  },
  {
   title: '排序号',
   dataIndex: 'item_sort',
   key: 'item_sort',
   width: '10%',
   sorter: true,
   scopedSlots: { customRender: 'item_sort' }
  },
  {
   title: '状态(1:正常,2:异常)',
   dataIndex: 'item_status',
   key: 'item_status',
   width: '10%',
   scopedSlots: { customRender: 'item_status' }
  },
  {
   title: '操作',
   key: 'action',
   scopedSlots: { customRender: 'operation' }
  }
  ],
  data: [],
  innerloading: false,
  parameter: {
  pageNo: 1,
  pageSize: 10
  },
  // 排序参数
  sortedInfo: null,
  pagination: {
  total: 1,
  current: 1,
  showTotal: total => `共 ${total} 条记录 第 ${this.pagination.current} / ${Math.ceil(total / this.pagination.pageSize)} 页`,
  showQuickJumper: true,
  showSizeChanger: true,
  pageSize: 10
  }

初始进入页面时,需要获取外层表格

使用初始参数parameter请求第一页数据,从返回数据中对pagination重置翻页组件内部参数,主要有当前页,页码总量,页码大小

getDictList(this.parameter)
  .then(res => {
   if (res.code === '200') {
   console.log(res)
   this.loadData = res.data
   this.pagination.total = res.totalCount
   this.pagination.current = res.pageNo
   this.pagination.pageSize = res.pageSize
   } else {
   this.$message.error(res.message)
   }
  })

展开外层数据节点获取内部数据:

expand (expanded, record) {
  this.expandedRowKeys = [] // 重置展开节点,只展开当前点击的节点(内部数据调用模板,无法做到同时几个内层表格数据直接缓存在页面)
  if (expanded) {
  this.expandedRowKeys = [record.dict_id]
  this.getDictItem() // 获取表格内部数据
  }
  console.log(expanded, record)
 },
// 展开节点后获取内部表格数据
getDictItem (obj) {
  let searchparam = { dict_id: this.expandedRowKeys[0] }
  if (obj) { // 内部表格除了根据其父节点id查找的条件外,还支持排序,因此需要整合排序参数
  searchparam = Object.assign(searchparam, obj)
  }
  this.innerloading = true
  getDictItemList(searchparam).then(res => {
  if (res.code === '200') {
   this.data = res.data
   this.innerloading = false
  } else {
   this.$message.error(res.message)
  }
  })
 },
// 外层表格操作
 change (pagination, filters, sorter) { // 对页面大小,筛选,排序等条件修改后重新查询数据
  this.pagination = pagination
  this.parameter.pageNo = pagination.current
  this.parameter.pageSize = pagination.pageSize
  this.getDict()
  console.log('pagination', pagination)
  console.log('filters', filters)
  console.log('sorter', sorter)
 },
 /* 内层表格操作 */
 innerhandleChange (pagination, filters, sorter) {
  console.log('Various parameters', pagination, filters, sorter)
  this.sortedInfo = {
  sortField: sorter.field,
  sortOrder: sorter.order
  }
  this.getDictItem(this.sortedInfo)
 },

至此,展示功能已经几乎做完啦,现在是内部表格的编辑与新增功能

handleChange (value, key, column) { // 实时更新表格中各个输入框的状态
  const newData = [...this.data]
  const target = newData.filter(item => key === item.key)[0]
  if (target) {
  target[column] = value
  this.data = newData
  }
 },
 toggle (data) { // 切换输入框与文本状态,实现展示与编辑功能
  const target = this.data.filter(item => item.key === data.key)[0]
  target.editable = !target.editable
  console.log(this.data)
 },
 newMember () { // 新增内容后的数据字段
  this.data.push({
  'item_text': '',
  'item_value': '',
  'item_checked': '',
  'item_remark': '',
  'item_sort': '',
  'item_status': '',
  key: this.data.length,
  editable: true,
  isNew: true
  })
 },
 saveRow (record) {
  this.innerloading = true
  if (!record.item_text || !record.item_value) { // 对必填项进行管控
  this.innerloading = false
  this.$message.error('请至少填写填写字段名和字段值。')
  return
  }
  record.item_checked = record.item_checked || 0 // 设置默认值
  record.item_sort = record.item_sort || 1
  record.item_status = record.item_status || 1
  record.dict_id = this.expandedRowKeys[0]
  if (record.item_id) { // 修改
  updateItem(record).then(res => {
   if (res.code === '200') {
   this.$message.success(res.message)
   this.getDictItem() // 修改成功后重新获取当前内部表格数据
   } else {
   this.$message.error(res.message)
   }
  })
  } else {
  addItem(record).then(res => {
   if (res.code === '200') {
   this.$message.success(res.message)
   this.getDictItem()
   } else {
   this.$message.error(res.message)
   }
  })
  }
 },
 cancel (key) {
  const target = this.data.filter(item => item.key === key)[0]
  target.editable = false
 },
 remove (key) {
  const newData = this.data.filter(item => item.key !== key)
  this.data = newData
 },
 /* 内层表格操作结束 */

外层表格与内存表格数据示例:

{
 "success": true,
 "code": "200",
 "message": "分页查询成功",
 "data": [{
 "dict_id": 1,
 "dict_code": "common_org_type",
 "dict_name": "机构类别",
 "dict_pid": null,
 "dict_status": 1,
 "dict_remark": "机构类别"
 }, {
 "dict_id": 2,
 "dict_code": "common_user_type",
 "dict_name": "人员类别",
 "dict_pid": null,
 "dict_status": 1,
 "dict_remark": "人员类别"
 }, {
 "dict_id": 48,
 "dict_code": "cdsfcsdcf",
 "dict_name": "修改属性1",
 "dict_pid": null,
 "dict_status": 1,
 "dict_remark": ""
 }, {
 "dict_id": 49,
 "dict_code": "bugbugbug",
 "dict_name": "有字典id",
 "dict_pid": null,
 "dict_status": 1,
 "dict_remark": ""
 }, {
 "dict_id": 50,
 "dict_code": "1",
 "dict_name": "名称",
 "dict_pid": null,
 "dict_status": 1,
 "dict_remark": "1"
 }, {
 "dict_id": 51,
 "dict_code": "1",
 "dict_name": "1",
 "dict_pid": null,
 "dict_status": 1,
 "dict_remark": null
 }, {
 "dict_id": 52,
 "dict_code": "1",
 "dict_name": "1",
 "dict_pid": null,
 "dict_status": 1,
 "dict_remark": null
 }, {
 "dict_id": 53,
 "dict_code": "1",
 "dict_name": "1",
 "dict_pid": null,
 "dict_status": 1,
 "dict_remark": null
 }, {
 "dict_id": 54,
 "dict_code": "1",
 "dict_name": "1",
 "dict_pid": null,
 "dict_status": 1,
 "dict_remark": ""
 }, {
 "dict_id": 55,
 "dict_code": "dbhasuiuh",
 "dict_name": "测试字典1",
 "dict_pid": null,
 "dict_status": 1,
 "dict_remark": "备注"
 }],
 "totalCount": 11,
 "pageNo": 1,
 "pageSize": 10,
 "totalTag": 1
}
{
 "success": true,
 "code": "200",
 "message": "查询成功",
 "data": [{
 "item_id": 2,
 "dict_id": 1,
 "item_text": "外部",
 "item_value": "2",
 "item_status": 1,
 "item_sort": 2,
 "item_remark": null,
 "item_checked": 1,
 "editable": 0 // 写死就行了 一定要有 用于内部表格编辑功能
 }, {
 "item_id": 1,
 "dict_id": 1,
 "item_text": "内部",
 "item_value": "1",
 "item_status": 1,
 "item_sort": 1,
 "item_remark": "1",
 "item_checked": 1,
 "editable": 0
 }]
}

补充知识:ant design Table可编辑的单元格改进版

antd官方也有给文档,但是超级麻烦,代码量还超级多,改编了一下

如图:

ant design vue嵌套表格及表格内部编辑的用法说明

这里table的columns的写法,如下:

const columns2 = [
{
title: '尺寸名称',
dataIndex: 'name',
filterDropdown: true,
filterIcon: <Icon type="edit"/>,
render: () => <Input />,
},
{
title: '标准尺寸',
dataIndex: 'standard',
filterDropdown: true,
filterIcon: <Icon type="edit"/>,
render:() => <Input />,
},
{
title: '上偏差',
dataIndex: 'upper_deviation',
filterDropdown: true,
filterIcon: <Icon type="edit"/>,
render:() => <Input />,
},
{
title: '下偏差',
dataIndex: 'lower_deviation',
filterDropdown: true,
filterIcon: <Icon type="edit"/>,
render: () => <Input />,
},
{
title: '工序',
dataIndex: 'procedure',
filterDropdown: true,
filterIcon: <Icon type="edit"/>,
render: () => 
<Select>
  <Option value='1'>1</Option>  
  <Option value='2'>2</Option> 
</Select>
},
{
title: '操作',
dataIndex: 'operation',
render: (text, record) => (
this.state.size.length >= 1
? (
<Popconfirm title="确定删除该信息?" onConfirm={() => this.handleDelete(record.key)}>
<a href="javascript:;">删除</a>
</Popconfirm>
) : null
),
}
];

其中

filterDropdown: true,

filterIcon: <Icon type="edit"/>,

这两个是用于给表头添加图标,不需要可以不写

实现可编辑表格最重要的是吧这个表格所有字段都变成可控字段,这样就可以实现对表格数据的提交的基本操作

就拿我这里面的尺寸名称来说,这个字段叫name ,这里的render就要修改成render: (text, record) => <Input value={text} onChange={(e) => this.handleChange({name: e.target.value}, record)}/>,

这里参数text可以理解为 input的初始值,onChange事件是吧这个input变成可控的组件,handleChange这里有两个参数,这里“”name: e.target.value“”必须要这么传,目的是把改组件的值跟name进行绑定。

handleChange 方法

handleChange = (value, record) => {
for (var i in value) {
record[i] = value[i];//这一句是必须的,不然状态无法更改
this.setState({
size: this.state.size.map((item, key) => item.key == record.key ? {...item, [i]: value[i]} : item)
})
}
}

这里我把这个可编辑表格的值存在state中的size中,通过key进行匹配(这里key代表我这个表格的rowkey,也就是用来区分行数据的一个标识),然后修改指定行的指定数据,通过改变state中的size更新视图,同时吧更改的数据替换掉原来的 这就实现了对表格数据的实时监听,同时表格的所有数据存在了state中的size中,想要获取表格数据直接用this.state.size即可。

(这里需要注意的时,如果把表格中的某个字段,比如说name设置成表格的rowkey,就会发生name字段只能输入单个字符就会失去焦点的情况)

以上这篇ant design vue嵌套表格及表格内部编辑的用法说明就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript中Array 对象相关的几个方法
Dec 22 Javascript
JavaScript 高级语法介绍
Jun 15 Javascript
javascript窗口宽高,鼠标位置,滚动高度(详细解析)
Nov 18 Javascript
JS控制输入框内字符串长度
May 21 Javascript
JavaScript Sort 的一个错误用法示例
Mar 20 Javascript
JS实现常见的TAB、弹出层效果(TAB标签,斑马线,遮罩层等)
Oct 08 Javascript
九种原生js动画效果
Nov 11 Javascript
JavaScript学习总结之JS、AJAX应用
Jan 29 Javascript
jQuery提示插件qTip2用法分析(支持ajax及多种样式)
Jun 08 Javascript
js设置文字颜色的方法示例
Dec 30 Javascript
bootstrap插件treeview实现全选父节点下所有子节点和反选功能
Jul 21 Javascript
Vue实现导航栏点击当前标签变色功能
Aug 19 Javascript
解决ant design vue 表格a-table二次封装,slots渲染的问题
Oct 28 #Javascript
ant design vue中表格指定格式渲染方式
Oct 28 #Javascript
vue实现一个矩形标记区域(rectangle marker)的方法
Oct 28 #Javascript
ant design vue datepicker日期选择器中文化操作
Oct 28 #Javascript
微信小程序picker组件两列关联使用方式
Oct 27 #Javascript
解决ant Design中this.props.form.validateFields未执行的问题
Oct 27 #Javascript
解决antd Form 表单校验方法无响应的问题
Oct 27 #Javascript
You might like
PHP+MySQL 手工注入语句大全 推荐
2009/10/30 PHP
PHP合并两个数组的两种方式的异同
2012/09/14 PHP
Yii快速入门经典教程
2015/12/28 PHP
yii2简单使用less代替css示例
2017/03/10 PHP
thinkphp5.1 框架导入/导出excel文件操作示例
2020/05/25 PHP
学习jquery必备 api中英文对照的chm手册 下载
2007/05/03 Javascript
JS跨域代码片段
2012/08/30 Javascript
jquery实现图片渐变切换兼容ie6/Chrome/Firefox
2013/08/02 Javascript
jQuery向上遍历DOM树之parents(),parent(),closest()之间的区别
2013/12/02 Javascript
js单词形式的运算符
2014/05/06 Javascript
jQuery实现的Div窗口震动特效
2014/06/09 Javascript
Jquery实现select multiple左右添加和删除功能的简单实例
2016/05/26 Javascript
详解Vue.js使用Swiper.js在iOS
2018/09/10 Javascript
关于vue组件事件属性穿透详解
2019/10/28 Javascript
多页vue应用的单页面打包方法(内含打包模式的应用)
2020/06/11 Javascript
html中创建并调用vue组件的几种方法汇总
2020/11/17 Javascript
使用python实现正则匹配检索远端FTP目录下的文件
2015/03/25 Python
python之PyMongo使用总结
2017/05/26 Python
老生常谈Python序列化和反序列化
2017/06/28 Python
速记Python布尔值
2017/11/09 Python
详谈Numpy中数组重塑、合并与拆分方法
2018/04/17 Python
python 读取摄像头数据并保存的实例
2018/08/03 Python
python正则爬取某段子网站前20页段子(request库)过程解析
2019/08/10 Python
3行Python代码实现图像照片抠图和换底色的方法
2019/10/10 Python
解决pytorch-yolov3 train 报错的问题
2020/02/18 Python
python 将html转换为pdf的几种方法
2020/12/29 Python
初级软件工程师面试题 Junior Software Engineer Interview
2015/02/15 面试题
小饰品店的创业计划书范文
2013/12/28 职场文书
教师节促销方案
2014/03/22 职场文书
政治思想表现评语
2014/05/04 职场文书
自查自纠工作情况报告
2014/10/29 职场文书
实施意见格式范本
2015/06/05 职场文书
高中语文教学反思范文
2016/02/16 职场文书
CSS预处理框架——Stylus
2021/04/21 HTML / CSS
Java移除无效括号的方法实现
2021/08/07 Java/Android
十大公认最好看的动漫:《咒术回战》在榜,《钢之炼金术师》第一
2022/03/18 日漫