vue、react动态新增行
在开发后台管理系统时基本都会有动态新增行,并可以编辑、保存、删除等功能,这个就需要我们动态添加行时生成唯一id或key (本人使用的时vue-antd UI)
此处我是在新增行触发编辑功能,所以可以直接编辑
考虑到删除时key的缺失,我们就在data中声明个单独的变量,点击新增使其自++,具体请看代码。里面有不需要代码请忽略
<template> <div> <div style="max-width: 80%; margin: 40px auto 0;"> <a-table :columns="columns" :data-source="data" bordered> <template v-for="col in ['cctv_name', 'cctv_rtsp', 'order']" :slot="col" slot-scope="text, record, index"> <div :key="col"> <a-input v-if="record.editable" style="margin: -5px 0" :value="text" @change="e => handleChange(e.target.value, record.key, col)" /> <template v-else> {{ text }} </template> </div> </template> <template slot="operation" slot-scope="text, record, index"> <div class="editable-row-operations"> <span v-if="record.editable"> <a href="javascript:;" @click="() => save(record.key)">保存</a> <a href="javascript:;" @click="() => cancel(record.key)">取消</a> </span> <span v-else> <a href="javascript:;" :disabled="editingKey !== ''" @click="() => edit(record.key)">编辑</a> <a href="javascript:;" @click="() => onDelete(record.key)">删除</a> </span> </div> </template> </a-table> <a-row type="flex" justify="center" class="video"> <a href="javascript:;" @click="added()"> + 新增视频点位</a> </a-row> </div> <a-form :form="form" style="max-width: 500px; margin: 40px auto 0;"> <a-form-item :wrapperCol="{ span: 19, offset: 5 }"> <a-button style="margin-right: 10px" @click="prevStep">上一步</a-button> <a-button :loading="loading" type="primary" @click="nextStep">下一步</a-button> </a-form-item> </a-form> </div> </template> <script> const columns = [ { title: '视频点位名称', dataIndex: 'cctv_name', width: '25%', scopedSlots: { customRender: 'cctv_name' } }, { title: 'rstp地址', dataIndex: 'cctv_rtsp', width: '15%', scopedSlots: { customRender: 'cctv_rtsp' } }, { title: '排序编号', dataIndex: 'order', width: '40%', scopedSlots: { customRender: 'order' } }, { title: '操作', dataIndex: 'operation', scopedSlots: { customRender: 'operation' } } ] // const data = [ // { // key: 1, // cctv_name: '', // cctv_rtsp: null, // order: '', // cctv_status: 'n' // } // ] import { CCTV, edge_device } from '@/api/factory' import bus from '@/Bus' export default { name: 'Step2', data() { // this.cacheData = data.map(item => ({ ...item })) return { uniq: '', labelCol: { lg: { span: 5 }, sm: { span: 5 } }, wrapperCol: { lg: { span: 19 }, sm: { span: 19 } }, form: null, loading: false, timer: 0, newTabIndex: 0, //初始key值 // 表格 data:[], columns, editingKey: '', cname: '1', //设备别名 mport: '11', //管理端口 vport: '9' //视频端口 } }, created() { // 通过中央控件兄弟传值 // bus.$on('sendByBus', val => { // console.log(val) // this.cname = val.cname // this.mport = val.mport // this.vport = val.vport // }) }, mounted() { this.uniq = this.$route.query.uniq if (this.uniq) { this.CCTVInfo() } }, methods: { CCTVInfo() { const params = { uniq: this.uniq } // 回显接口 CCTV(params).then(res => { console.log(res) }) }, nextStep() { console.log(this.data) const params = { cname: this.cname, edge_cctv_array: this.data, mport: this.mport, vport: this.vport } // 新建接口 edge_device(params).then(res => { if (res.code === '00000') { this.loading = true setTimeout(() => { this.loading = false this.$emit('nextStep') }, 1000) } }) }, prevStep() { this.$emit('prevStep') }, // 表格 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 } }, //编辑 edit(key) { console.log(key) const newData = [...this.data] const target = newData.filter(item => key === item.key)[0] this.editingKey = key if (target) { target.editable = true this.data = newData } }, //保存 save(key) { console.log(key) const newData = [...this.data] // const newCacheData = [...this.cacheData] const target = newData.filter(item => key === item.key)[0] // const targetCache = newCacheData.filter(item => key === item.key)[0] if (target) { delete target.editable this.data = newData console.log(this.data) // Object.assign(targetCache, target) // this.cacheData = newData // console.log(this.cacheData) } this.editingKey = '' }, // 取消 cancel(key) { const newData = [...this.data] const target = newData.filter(item => key === item.key)[0] this.editingKey = '' if (target) { // Object.assign(target, this.cacheData.filter(item => key === item.key)[0]) delete target.editable this.data = newData } }, // 删除 onDelete(key) { console.log(key) const data = [...this.data] this.data = data.filter(item => item.key !== key) }, // 新增 added(val) { const activeKey = `newKey${this.newTabIndex++}` this.data.push({ // key: (this.data.length + 1).toString(), key: activeKey, cctv_name: '', cctv_rtsp: null, order: '', cctv_status: 'n' }) this.edit(activeKey) } }, beforeDestroy() { clearTimeout(this.timer) } } </script> <style lang="less" scoped> .video { margin-top: 3px; padding: 3px 0; border: 1px dotted #ccc; a { color: #1890ff; } } .editable-row-operations a { margin-right: 8px; } .stepFormText { margin-bottom: 24px; .ant-form-item-label, .ant-form-item-control { line-height: 22px; } } /deep/.ant-table-pagination.ant-pagination { display: none; } </style>