vue + element 实现可编辑列表(超详细)
vue + element 实现可编辑列表(超详细)
1.适用场景
当我们对于主子表数据同时保存的时候,我们又不想做弹窗一条一条的新增子表数据的时候,并且子表数据并不是特别复杂,完全可用table来操作,这种情况下可选择可编辑列表来完成主子表的同时操作。
2.功能简介
基于Tlement-Table编写,并借助于一些表单元素控件。实现表格数据的填写。以及表格操作,包括:新增行,删除行,插入行,上移,下移,置顶,置底等功能。废话不多说直接上代码。
3.页面布局
包含对每一行数据的简单校验。
<template>
<el-row>
<el-card>
<el-row class="text-right m-b">
<el-button type="primary" @click="handleAdd()">
添加行
</el-button>
<el-button type="danger" plain @click="batchRemove">
删除行
</el-button>
<el-button type="primary" @click="handleInsert">
插入行
</el-button>
<el-button type="primary" @click="handleMove(1)">
上移
</el-button>
<el-button type="primary" @click="handleMove(0)">
下移
</el-button>
<el-button type="primary" @click="handleTopOrBottom(1)">
置顶
</el-button>
<el-button type="primary" @click="handleTopOrBottom(0)">
置底
</el-button>
<el-button type="primary" @click="clearList">
清空
</el-button>
</el-row>
<el-form ref="form2" :model="submitData" :rules="rules" label-width="150px">
<el-row :span="24">
<el-table
ref="studentTable"
:data="submitData.studentTableData"
style="width: 100%"
highlight-current-row
stripe
border
:row-class-name="tableRowClassName"
@current-change="currentChange"
@selection-change="clickLogCheckboxHandler"
>
<el-table-column
type="index"
label="序号"
width="80"
/>
<el-table-column
prop="studentCode"
label="学号"
>
<template slot-scope="scope">
<el-form-item :prop="'studentTableData.'+scope.$index+'.studentCode'" :rules="rules.studentTableDataRules.studentCode" label-width="0">
<el-input v-if="scope.row.showFormDom" v-model="scope.row.studentCode"/>
<div v-else>
{{ scope.row.studentCode }}
</div>
</el-form-item>
</template>
</el-table-column>
<el-table-column
prop="studentName"
label="学生姓名"
>
<template slot-scope="scope">
<el-form-item :prop="'studentTableData.'+scope.$index+'.studentName'" :rules="rules.studentTableDataRules.studentName" label-width="0">
<el-input v-if="scope.row.showFormDom" v-model="scope.row.studentName"/>
<div v-else>
{{ scope.row.studentName }}
</div>
</el-form-item>
</template>
</el-table-column>
<el-table-column
prop="studentAge"
label="学生年龄"
>
<template slot-scope="scope">
<el-form-item :prop="'studentTableData.'+scope.$index+'.studentAge'" :rules="rules.studentTableDataRules.studentAge" label-width="0">
<el-input v-if="scope.row.showFormDom" v-model="scope.row.studentAge"/>
<div v-else>
{{ scope.row.studentAge }}
</div>
</el-form-item>
</template>
</el-table-column>
<el-table-column
prop="studentSex"
label="学生性别"
>
<template slot-scope="scope">
<el-form-item :prop="'studentTableData.'+scope.$index+'.studentSex'" :rules="rules.studentTableDataRules.studentSex" label-width="0">
<el-input v-if="scope.row.showFormDom" v-model="scope.row.studentSex"/>
<div v-else>
{{ scope.row.studentSex }}
</div>
</el-form-item>
</template>
</el-table-column>
</el-table>
</el-row>
<el-row class="text-center m-t">
<el-button type="primary" @click="submitHandler">
保存
</el-button>
</el-row>
</el-form>
</el-card>
</el-row>
</template>
4.数据声明
data() {
return {
// 选中的行
selected: null,
rowIndex: 0,
// 提交数据
submitData: {
studentTableData: []
},
// 校验信息
rules: {
studentTableDataRules: {
studentName: [
{ required: true, message: '请输入学生姓名', trigger: 'blur' }
],
studentCode: [
{ required: true, message: '请输入学号', trigger: 'blur' }
],
studentAge: [
{ required: true, message: '请输入学生年龄', trigger: 'blur' }
],
studentSex: [
{ required: true, message: '请输入学生性别', trigger: 'blur' }
]
}
},
// 多选情况下多选数据存储
selecteds: []
}
}
5.功能实现
5.1 获取选中的行
注:多选情况。
clickLogCheckboxHandler(selection) {
this.selecteds = selection
}
5.2 为row添加索引
注:由于row中获取不到索引值,无法操作数组中的数据,因此增加此方法为row增加索引值。
tableRowClassName({ row, rowIndex }) {
row.row_index = rowIndex
}
5.3 新增行
注:此方法为列表底部新增一行,新增前会执行校验,并且新增行获得高亮;高亮方法为element-ui提供。
handleAdd() {
const list = {
studentCode: '',
studentName: '',
studentAge: '',
studentSex: '',
showFormDom: true
}
this.$refs['form2'].validate((valid) => {
if (valid) {
if (this.selected !== null) {
const index = this.selected.row_index
this.$set(this.submitData.studentTableData[index], 'showFormDom', false)
}
this.submitData.studentTableData.push(list)
this.selected = list
this.selected.row_index = this.submitData.studentTableData.length - 1
this.$refs.studentTable.setCurrentRow(this.submitData.studentTableData[this.selected.row_index])
} else {
// 此处为验证失败代码
this.$message.warning('请先为当前行填值!')
}
})
}
5.4 删除行
注:删除当前选中行
batchRemove() {
this.$confirm('确认删除选中记录吗?', '提示', {
type: 'warning'
})
.then(() => {
if (this.selected !== null) {
this.submitData.studentTableData.splice(this.selected.row_index, 1)
this.selected = null
this.$message({
message: '删除成功',
type: 'success'
})
} else {
this.$message({
message: '请选择要删除的行!',
type: 'warning'
})
}
})
.catch(() => {})
}
5.5 插入行
注:在选中数据上方插入一个空行
handleInsert() {
if (this.selected !== null) {
const list = {
studentCode: '',
studentName: '',
studentAge: '',
studentSex: '',
showFormDom: true
}
if (this.submitData.studentTableData.length > 0) {
this.$refs['form2'].validate((valid) => {
if (valid) {
const index = this.selected.row_index
this.$set(this.submitData.studentTableData[index], 'showFormDom', false)
this.submitData.studentTableData.splice(index, 0, list)
this.selected = list
this.selected.row_index = index
this.$refs.studentTable.setCurrentRow(this.submitData.studentTableData[index])
} else {
// 此处为验证失败代码
this.$message.warning('请先为当前行填值!')
}
})
} else {
this.submitData.studentTableData.push(list)
this.selected = list
this.selected.row_index = 0
this.$refs.studentTable.setCurrentRow(this.submitData.studentTableData[0])
}
} else {
this.$message.warning('请选择插入位置!')
}
}
5.6 上移,下移
注:根据传入标识判断上移,下移(1:上移;0:下移)
handleMove(dir) {
if (this.selected !== null) {
const moveComm = (curIndex, nextIndex) => {
const arr = this.submitData.studentTableData
arr[curIndex] = arr.splice(nextIndex, 1, arr[curIndex])[0]
return arr
}
this.submitData.studentTableData.some((val, index) => {
if (val.studentCode === this.selected.studentCode) {
if (dir === 1 && index === 0) {
this.$message.warning('已在顶部!')
} else if (dir === 0 && index === this.submitData.studentTableData.length - 1) {
this.$message.warning('已在底部!')
} else {
const nextIndex = dir === 1 ? index - 1 : index + 1
this.submitData.studentTableData = moveComm(index, nextIndex)
}
return true
}
return false
})
} else {
this.$message.warning('请选择操作的行!')
}
}
5.7 置顶/置底
注:根据传入标识判断置顶/置底(1:置顶;0:置底)
handleTopOrBottom(dir) {
if (this.selected !== null) {
const moveComm = (curIndex, nextIndex) => {
const arr = this.submitData.studentTableData
arr[curIndex] = arr.splice(nextIndex, 1, arr[curIndex])[0]
return arr
}
this.submitData.studentTableData.some((val, index) => {
if (val.studentCode === this.selected.studentCode) {
if (dir === 1 && index === 0) {
this.$message.warning('已在顶部!')
} else if (dir === 0 && index === this.submitData.studentTableData.length - 1) {
this.$message.warning('已在底部!')
} else {
const nextIndex = dir === 1 ? 0 : this.submitData.studentTableData.length - 1
this.submitData.studentTableData = moveComm(index, nextIndex)
}
return true
}
return false
})
} else {
this.$message.warning('请选择操作的行!')
}
}
5.8 清空列表
注:vue基于数据驱动,清空列表只需要清空列表数组数据即可。
clearList() {
this.$confirm('确认执行清空操作吗?', '提示', {
type: 'warning'
})
.then(() => {
this.submitData.studentTableData = []
this.selected = null
this.$message({
message: '清空完成!',
type: 'success'
})
})
}
5.9 改变列表选中
注:由于这次编写的可编辑列表有这样一个特性,即:选中的行才可以编辑,未选中的行则是只读状态。因此在改变选中时应该增加一些操作。例如:对row.showFormDom的操作。还是直接看代码:
currentChange(newRow, oldRow) {
if (this.selected !== null) {
if (newRow.row_index !== this.selected.row_index) {
this.$refs['form2'].validate((valid) => {
if (valid) {
const index = this.selected.row_index
this.$set(this.submitData.studentTableData[newRow.row_index], 'showFormDom', true)
this.$set(this.submitData.studentTableData[index], 'showFormDom', false)
this.selected = newRow
} else {
// 此处为验证失败代码
this.$refs.studentTable.setCurrentRow(this.submitData.studentTableData[this.selected.row_index])
// this.$message.warning('请先为当前行填值!')
}
})
}
} else {
this.$set(this.submitData.studentTableData[newRow.row_index], 'showFormDom', true)
this.selected = newRow
}
}
5.10 最终操作:保存
注:这个应该无须赘述。
submitHandler() {
this.$refs['form2'].validate((valid) => {
if (valid) {
this.$message({
showClose: true,
message: '请完善列表中的数据!',
type: 'warning'
})
} else {
this.$message({
showClose: true,
message: '请完善列表中的数据!',
type: 'warning'
})
}
})
}
6 总结
可编辑列表常用的基本功能大致就想到了这么多,在就是本demo中表单元素均用input实现,对于其他需求,可以替换为其他表单元素控件,例如:select等。也可针对于字段值的改变触发一些特定的方法来实现特定的需求。再就是上移、下移、置顶、置底均用到了studentCode这个属性,那么这个属性应该保持其唯一性,这里没有为其增加唯一性校验,实际开发中应该注意。再就是习惯js的=赋值,在这里很多采用了$set去赋值,有时间我会单独聊一下这样赋值的原因。
最后希望大家开源自己,共同进步。
更多推荐
所有评论(0)