【需求】通过vue将下面的数据,填充到表格中,并实现数据的删除、修改操作。
【提前准备】搭建好一个vue工程,并安装好element-plus依赖配置。
[{
id: 1,
name: "查看项目列表接口_INlove即时通讯项目",
tester: "酷巴戈",
project: "INlove即时通讯项目",
project_id: 2,
desc: "",
create_time: "2023-11-06 17:22:50",
testcases: 1
},
{
id: 2,
name: "登录接口_自动化测试平台项目",
tester: "csdn",
project: "自动化测试平台项目",
project_id: 1,
desc: "登录接口",
create_time: "2023-12-06 14:50:30",
testcases: 9
},
{
id: 3,
name: "注册接口_自动化测试平台项目",
tester: "CC",
project: "自动化测试平台项目",
project_id: 1,
desc: "自动化测试平台项目,注册接口",
create_time: "2019-11-06 14:51:00",
testcases: 0
},
{
id: 4,
name: "创建项目接口_自动化测试平台项目",
tester: "DD",
project: "自动化测试平台项目",
project_id: 1,
desc: "这是自动化测试平台创建项目接口",
create_time: "2019-11-06 14:51:45",
testcases: 1
},
{
id: 5,
name: "注册接口_INlove即时通讯项目",
tester: "csdn",
project: "前程贷P2P金融项目",
project_id: 2,
desc: "",
create_time: "2019-11-06 14:52:22",
testcases: 0
},
{
id: 6,
name: "登录接口_INlove即时通讯项目",
tester: "小猴子",
project: "INlove即时通讯项目",
project_id: 2,
desc: "",
create_time: "2019-11-06 14:52:40",
testcases: 0
}],
【分析需求】
【对数据实行删除和修改】意味着,在每一行的数据右侧或左侧都存在两个按钮,删除和修改,那就是要在上一个版本的代码中,增加一个列,列里面增加两个按钮,这个用v-for也比较好实现。
【删除功能】单击按钮,要能够删除数据成功,意味着,单击删除按钮后,要获取到这一行的数据,并准确的删除了该行数据,且在列表里不显示改行数据。
【修改功能】也就是单击修改,要弹出一个对话框,并带出那些字段和数据,对应修改了任意一个字段后(暂且先不考虑是否必填)能够保存成功,没有修改关闭对话框后,能够保持原样。
【处理需求】
如想直接看代码,可滑到底部。
在这次的需求里,会用到vue工程项目,使用element-plus组件来实现。如果搭建vue工程项目,如何引入element-plus,可以看这篇文章:搭建vue工程项目,引入element-plus。(后续补充)
1、使用element-plus的标签完成循环遍历数据,添加删除和修改按钮
因为此次需要使用vue工程项目,利用element-plus来实现需求,所以代码需要重新编写。先去element-plus组件指南中找到符合想要的table,这两个选择任意一个即可。1、element-plus 2、element
找到一个比较符合此次需求的table,点击右侧按钮,复制代码,并将部分代码拷贝至App.vue文件中。
对App.vue的代码进行修改:表头、data、按钮,并使其符合vue文件的一般格式。修改后代码如下:
<template>
<el-table :data="usercases" style="width: 100%" border>
<el-table-column fixed prop="id" label="ID" width="50" />
<el-table-column prop="name" label="接口名" width="280" />
<el-table-column prop="tester" label="测试人员" width="120" />
<el-table-column prop="project" label="项目" width="200" />
<el-table-column prop="project_id" label="项目ID" width="120" />
<el-table-column prop="desc" label="描述" width="200" />
<el-table-column prop="create_time" label="创建时间" width="200" />
<el-table-column prop="testcases" label="用例数" width="100" />
<el-table-column fixed="right" label="操作" width="120">
<template #default>
<el-button link type="primary" size="small" @click="handleClick">删除</el-button>
<el-button link type="primary" size="small">修改</el-button>
</template>
</el-table-column>
</el-table>
</template>
<script>
export default {
handleClick() {
console.log('click')
},
data() {
return{
usercases: [{
id: 1,
name: "查看项目列表接口_INlove即时通讯项目",
tester: "酷巴戈",
project: "INlove即时通讯项目",
project_id: 2,
desc: "",
create_time: "2023-11-06 17:22:50",
testcases: 1
},
{
id: 2,
name: "登录接口_自动化测试平台项目",
tester: "csdn",
project: "自动化测试平台项目",
project_id: 1,
desc: "登录接口",
create_time: "2023-12-06 14:50:30",
testcases: 9
}
]
}
}
}
</script>
2、删除功能
【删除功能】,需要:
- 单击删除按钮,调起二次删除确认;
- 二次确认后,将该行数据删除,并关闭二次确认对话框;
- 二次确认取消后,该行数据保留,并关闭二次确认对话框。
2.1、调起对话框
明确接下来要做的之后,我们去element-plus组件库看看有没有符合我们需求的组件。
还是跟第一步一样,看看源码,再选择复制到App.vue文件中。
复制并适当修改后,代码如下:
<template>
//其他代码
</template>
<script>
import {
ElMessage,
ElMessageBox
} from 'element-plus'
export default {
methods: {
deleteButton() {
ElMessageBox.confirm(
'是否确认删除',
'提醒', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
ElMessage({
type: 'success',
message: '删除成功',
})
})
.catch(() => {
ElMessage({
type: 'info',
message: '删除取消',
})
})
},
},
data() {
return {
// 其他代码
}
},
}
</script>
<style scoped>
// 其他代码
</style>
2.2、删除数据
可以发现,这个组件满足了1、3,但没有满足2。
那是因为在遍历删除按钮的时候,就没有给那一行的数据进行赋值;更没有在二次确认删除的时候,把这行数据传过去,也没有对该行数据做任何处理,而只是给了个message删除成功。
因此我们在这两处分别进行修改:
1)在每行遍历数据data中的usercases数据和删除、修改按钮时,拿到每一行的数据对象。
#default="{row}"
是解构赋值的写法,它表示默认插槽的内容将会被传递给一个包含当前行数据的对象 row
。
这种写法很方便在插槽内部直接使用当前行的数据,如 @click="deleteButton(row) 事件传递row进去,就可以对该行数据进行事件操作。
<template #default="{row}">
<el-button link type="primary" size="small" @click="deleteButton(row)">删除</el-button>
<el-button link type="primary" size="small">修改</el-button>
</template>
2)把data中的usercases数据进行过滤,通过 filter
方法只保留那些不等于 row
的元素。
-
filter
方法接受一个回调函数,回调函数会对数组中的每个元素执行一次。在这里,回调函数是(item) => item !== row
。它的作用是检查每个元素是否不等于row
。
-
item
是回调函数的参数,表示数组中的每个元素。在本代码中,item
就是this.usercases
数组中的一个用户案例。
-
当回调函数
(item) => item !== row
返回true
时,item
就会被保留在过滤后的数组中;当返回false
时,item
就会被排除在外。
.then(() => {
this.usercases = this.usercases.filter((item) => item !== row);
ElMessage({
type: 'success',
message: '删除成功',
})
})
至此,我们就实现了删除功能
3、修改功能
修改功能如要实现,须满足以下小功能:
- 弹出对话框(确认则提交,取消则返回)
- 带出原数据
- 保存新数据,覆盖原数据
3.1、弹出对话框
和删除功能不同的,修改的对话框,须支持数据输入。所以可以在删除的对话框上进行改进,也可以再在element-plus中找一个带输入框的组件。
这个比较符合此次的需求,我们来对它源码template 里的内容来仔细阅读下。
script标签内的内容,不太符合目前所学的vue工程项目里的写法,暂且不管。还是按照当前的结构来写。
3.2、带出原数据
通过分析组件源码可以知道:
- 它将整个对话框定义了一个dialogFormVisible的属性,并在(1)单击修改按钮的时候,(2)单击确认的时候,(3)单击取消的时候,都会变化这个属性的值。那么我们就不能仅仅用单向绑定v-bind来绑定这个属性,而是要双向绑定。如果为单向绑定的话,就只是一直在获取它的初始值,而假如初始值是true,那么就无法让它动态可视化。
- 弹框里的数据单向绑定了form的数据。但实际案例中,已经存在一个usercases数组,不可能将usercases数组去绑定到<el-form>标签中。
- 单击确认按钮后,触发了【让对话框不可见】的事件,但实际上,我们还需要让数据update到表格中。
3.2.1、对话框可视化
增加一个dialogFormVisible的属性在data中,我选择叫它editDialogVisible。
<template>
<!-- 其他代码 -->
<el-dialog v-model="editDialogVisible" title="编辑案例">
<el-form v-model="form">
<el-form-item label="ID" :label-width="formLabelWidth">
<el-input v-model="form.id" autocomplete="off" />
</el-form-item>
<el-form-item label="接口名" :label-width="formLabelWidth">
<el-input v-model="form.name" autocomplete="off" />
</el-form-item>
<el-form-item label="测试人员" :label-width="formLabelWidth">
<el-input v-model="form.tester" autocomplete="off" />
</el-form-item>
<el-form-item label="项目" :label-width="formLabelWidth">
<el-input v-model="form.project" autocomplete="off" />
</el-form-item>
<el-form-item label="项目ID" :label-width="formLabelWidth">
<el-input v-model="form.project_id" autocomplete="off" />
</el-form-item>
<el-form-item label="描述" :label-width="formLabelWidth">
<el-input v-model="form.desc" autocomplete="off" />
</el-form-item>
<el-form-item label="创建时间" :label-width="formLabelWidth">
<el-input v-model="form.create_time" autocomplete="off" />
</el-form-item>
<el-form-item label="用例数" :label-width="formLabelWidth">
<el-input v-model="form.testcases" autocomplete="off" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogFormVisible = false">取消</el-button>
<el-button type="primary" @click="dialogFormVisible = false">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script>
import {
ElMessage,
ElMessageBox
} from 'element-plus'
export default {
data() {
return {
usercases: [
//案例数据
],
editDialogVisible: false,
}
},
methods: {
// 其他代码
}
}
</script>
<style scoped>
</style>
3.2.2、绑定临时数据
对话框弹出的时候,如果用删除功能里的代码,可以用row来表示展示的数据。单击修改,则展示该行数据。
我的处理方法是,用row获取到该行数据后,并写给tempcase。那么就可以在<el-input>标签里,绑定tempcase的id、name等等。巧妙的是,row的获取,在删除功能那部分代码就已经实现了。
<template>
<el-table :data="usercases" style="width: 100%" border :key='id'>
<!-- 其他代码 -->
<el-table-column fixed="right" label="操作" width="120">
<template #default="{row}">
<el-button link type="primary" size="small" @click="deleteButton(row)">删除</el-button>
<el-button link type="primary" size="small" @click='editCase(row)'>修改</el-button>
</template>
</el-table-column>
</el-table>
<!-- 编辑对话框 -->
<el-dialog v-model="editDialogVisible" title="编辑案例">
<el-form v-model="tempcase">
<el-form-item label="ID" :label-width="formLabelWidth">
<el-input v-model="tempcase.id" autocomplete="off" />
</el-form-item>
// 其他代码
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogFormVisible = false">取消</el-button>
<el-button type="primary" @click="dialogFormVisible = false">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script>
import {
ElMessage,
ElMessageBox
} from 'element-plus'
export default {
data() {
return {
usercases: [// 案例],
tempcase: {
id: null,
name: "",
tester: "",
project: "",
project_id: null,
desc: "",
create_time: "",
testcases: null
},
editDialogVisible: false,
}
},
methods: {
// 其他代码
editCase(row) {
// 将编辑用例的对话框设为可见
this.editDialogVisible = true;
// 将当前行的数据赋值给 tempcase,这样对话框中的表单就会显示当前行的值
this.tempcase = {
...row
};
},
},
}
</script>
<style scoped>
</style>
在这段代码中, {...row}
表示将 row
对象中的所有属性复制到一个新的对象中。this.tempcase={...row}
后,tempcase对象包含了 row
对象中的所有属性,但是与 row
对象是两个独立的对象。通过这种方式,可以确保在修改 tempcase
对象时不会直接影响 row
对象。
我们来看看现在的效果:
3.3、保存新数据
前面提到,原组件单击确认按钮后,触发了【让对话框不可见】的事件,但实际上,我们还需要让数据update到表格中。所以,我们是不是可以定义一个方法,包括了【不可见】和【保存数据】呢?
methods: {
// 其他代码
confirmEdit() {
const index = this.usercases.findIndex((item) => item.id === this.tempcase.id); //能找到就返回正常的索引id,找不到就返回-1
if (index !== -1) {
this.usercases.splice(index, 1, {
...this.tempcase
});
ElMessage.success('编辑成功');
this.editDialogVisible = false;
} else {
ElMessage.error('未找到相应项');
}
}
}
在此段代码中, {...this.tempcase}
和前面 {...row}
一样理解。
-
findIndex
是数组的方法之一,用来找到符合条件的元素在数组中的索引
-
(item) => item.id === this.tempcase.id
:这是一个箭头函数,用来定义findIndex
方法中的条件。它表示对usecases数组中的每个元素item
,检查其id
属性是否等于this.tempcase.id
。如果找到了,返回该元素在数组中的索引;如果没有找到,返回 -1。
-
需要注意的是,因为此处的判断条件是item.id,所以如果这个id变化了,那么是会找不到元素的,所以需要把id的input设置成只读状态。
-
一旦找到符合条件的元素,使用
splice
方法对数组进行修改。splice
方法的参数是(start, deleteCount, item1, item2, ...)
。这里的index
是找到的元素的索引,1
是要删除的元素数量,然后是{...this.tempcase}
,表示将this.tempcase
对象的属性添加到数组中的index
位置。这样就实现了对数组中特定元素的替换。
如此,便是实现了新数据的保存。最后,附上完整代码。
<template>
<el-table :data="usercases" style="width: 100%" border :key='id'>
<el-table-column fixed prop="id" label="ID" width="50" />
<el-table-column prop="name" label="接口名" width="280" />
<el-table-column prop="tester" label="测试人员" width="120" />
<el-table-column prop="project" label="项目" width="200" />
<el-table-column prop="project_id" label="项目ID" width="120" />
<el-table-column prop="desc" label="描述" width="200" />
<el-table-column prop="create_time" label="创建时间" width="200" />
<el-table-column prop="testcases" label="用例数" width="100" />
<el-table-column fixed="right" label="操作" width="120">
<template #default="{row}">
<el-button link type="primary" size="small" @click="deleteButton(row)">删除</el-button>
<el-button link type="primary" size="small" @click='editCase(row)'>修改</el-button>
</template>
</el-table-column>
</el-table>
<!-- 编辑对话框 -->
<el-dialog v-model="editDialogVisible" title="编辑案例">
<el-form v-model="tempcase">
<el-form-item label="ID" :label-width="formLabelWidth">
<el-input v-model="tempcase.id" autocomplete="off" readonly /> // 只读
</el-form-item>
<el-form-item label="接口名" :label-width="formLabelWidth">
<el-input v-model="tempcase.name" autocomplete="off" />
</el-form-item>
<el-form-item label="测试人员" :label-width="formLabelWidth">
<el-input v-model="tempcase.tester" autocomplete="off" />
</el-form-item>
<el-form-item label="项目" :label-width="formLabelWidth">
<el-input v-model="tempcase.project" autocomplete="off" />
</el-form-item>
<el-form-item label="项目ID" :label-width="formLabelWidth">
<el-input v-model="tempcase.project_id" autocomplete="off" />
</el-form-item>
<el-form-item label="描述" :label-width="formLabelWidth">
<el-input v-model="tempcase.desc" autocomplete="off" />
</el-form-item>
<el-form-item label="创建时间" :label-width="formLabelWidth">
<el-input v-model="tempcase.create_time" autocomplete="off" />
</el-form-item>
<el-form-item label="用例数" :label-width="formLabelWidth">
<el-input v-model="tempcase.testcases" autocomplete="off" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="cancelSubmit">取消</el-button>
<el-button type="primary" @click="confirmEdit">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script>
import {
ElMessage,
ElMessageBox
} from 'element-plus'
export default {
data() {
return {
usercases: [{
id: 1,
name: "查看项目列表接口_INlove即时通讯项目",
tester: "酷巴戈",
project: "INlove即时通讯项目",
project_id: 2,
desc: "",
create_time: "2023-11-06 17:22:50",
testcases: 1
},
{
id: 2,
name: "登录接口_自动化测试平台项目",
tester: "csdn",
project: "自动化测试平台项目",
project_id: 1,
desc: "登录接口",
create_time: "2023-12-06 14:50:30",
testcases: 9
}
],
tempcase: {
id: null,
name: "",
tester: "",
project: "",
project_id: null,
desc: "",
create_time: "",
testcases: null
},
editDialogVisible: false,
}
},
methods: {
deleteButton(row) {
ElMessageBox.confirm(
'是否确认删除',
'提醒', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
this.usercases = this.usercases.filter((item) => item !== row);
ElMessage({
type: 'success',
message: '删除成功',
})
})
.catch(() => {
ElMessage({
type: 'info',
message: '删除取消',
})
})
},
cancelSubmit(){
this.editDialogVisible = false;
},
editCase(row) {
// 将编辑用例的对话框设为可见
this.editDialogVisible = true;
// 将当前行的数据赋值给 tempcase,这样对话框中的表单就会显示当前行的值
this.tempcase = {
...row
};
},
confirmEdit() {
const index = this.usercases.findIndex((item) => item.id === this.tempcase.id); //能找到就返回正常的索引id,找不到就返回-1
if (index !== -1) {
this.usercases.splice(index, 1, {
...this.tempcase
});
// 提示编辑成功
ElMessage.success('编辑成功');
// 关闭编辑对话框
this.editDialogVisible = false;
} else {
ElMessage.error('未找到相应项');
}
}
},
}
</script>
<style scoped>
</style>
下一篇:表格增加数据