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的执行速度
Jan 23 Javascript
用js通过url传参把数据从一个页面传到另一个页面
Sep 01 Javascript
IE及IE6浏览器中判断JS文件加载成功失败的方法
Feb 18 Javascript
AngularJS 执行流程详细介绍
Aug 18 Javascript
老生常谈javascript变量的命名规范和注释
Sep 29 Javascript
微信小程序组件 contact-button(客服会话按钮)详解及实例代码
Jan 10 Javascript
AngularJS实现使用路由切换视图的方法
Jan 24 Javascript
Angular2中select用法之设置默认值与事件详解
May 07 Javascript
Easyui在treegrid添加控件的实现方法
Jun 23 Javascript
VueCli3构建TS项目的方法步骤
Nov 07 Javascript
vue设置一开始进入的页面教程
Oct 28 Javascript
vue项目前端微信JSAPI与外部H5支付相关实现过程及常见问题
Apr 14 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
PHP5.2中date()函数显示时间与北京时间相差8小时的解决办法
2009/05/28 PHP
shell脚本作为保证PHP脚本不挂掉的守护进程实例分享
2013/07/15 PHP
php加速器eAccelerator的配置参数、API详解
2014/05/05 PHP
深入理解PHP中的Streams工具
2015/07/03 PHP
prototype 中文参数乱码解决方案
2009/11/09 Javascript
js中将HTMLCollection/NodeList/伪数组转换成数组的代码
2011/07/31 Javascript
jquery.artwl.thickbox.js  一个非常简单好用的jQuery弹出层插件
2012/03/01 Javascript
JavaScript实现定时隐藏与显示图片的方法
2015/08/06 Javascript
json定义及jquery操作json的方法
2016/09/29 Javascript
jQuery的事件预绑定
2016/12/05 Javascript
javascript过滤数组重复元素的实现方法
2017/05/03 Javascript
VUE利用vuex模拟实现新闻点赞功能实例
2017/06/28 Javascript
简单实现js进度条加载效果
2020/03/25 Javascript
React-Native中props具体使用详解
2017/09/04 Javascript
js异步上传多张图片插件的使用方法
2018/10/22 Javascript
详解JQuery基础动画操作
2019/04/12 jQuery
layui输入框只允许输入中文且判断长度的例子
2019/09/18 Javascript
Vue computed 计算属性代码实例
2020/04/22 Javascript
梳理一下vue中的生命周期
2020/12/30 Vue.js
Python处理JSON时的值报错及编码报错的两则解决实录
2016/06/26 Python
python2 与 python3 实现共存的方法
2018/07/12 Python
Python自定义函数计算给定日期是该年第几天的方法示例
2019/05/30 Python
Django对接支付宝实现支付宝充值金币功能示例
2019/12/17 Python
Python docutils文档编译过程方法解析
2020/06/23 Python
python实现画图工具
2020/08/27 Python
HTML5跳转小程序wx-open-launch-weapp的示例代码
2020/07/16 HTML / CSS
ASICS印度官方网站:日本专业运动品牌
2020/06/20 全球购物
医护人员英文求职信范文
2013/11/26 职场文书
满月酒答谢词
2014/01/14 职场文书
幼儿园开学家长寄语
2014/01/19 职场文书
教堂婚礼主持词
2014/03/14 职场文书
房屋出租协议书范本(标准版)
2014/09/24 职场文书
党员个人自我剖析材料
2014/10/08 职场文书
悬崖上的金鱼姬观后感
2015/06/15 职场文书
大学生干部培训心得体会
2016/01/06 职场文书
导游词之贵州织金洞
2019/10/12 职场文书