本文主要是介绍手摸手用element实现列表增删改查,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
表单界面涉及到数据的操作,会有几个关键点
- 表单的双向绑定v-model
- 表格的分页处理
- 新增和编辑的dialog,弹窗删除的dialog
index.vue文件解析
<template><div><!-- 条件查询 --><el-form/><!-- 表格 --><el-table/><!-- 分页组件 --><el-pagination/><!-- 弹框 --><Edit/></div></template>
<script>
import api from "@/api/category"; //接口
import Edit from "./edit"; //弹窗
export default {
// 注册后使用components: {Edit,},data() {return {}},// 钩子函数获取数据 created() {this.fetchData();},//方法methods: {}
}
</script>
1.首先实现类别列表功能,包含数据列表、分页、条件查询 。
列表接口
请求URL: /article/category/search
请求方式: post
描述:文章类别分页条件查询列表
Api 调用接口
- 在 src/api 下创建 category.js , 调用接口代码如下:
import request from '@/utils/request'
export default {//分类查询列表getList(query, current = 1, size = 20) {return request({url: `/article/category/search`,method: 'post',data: {...query,current,size}})}}
- 在 src\views\category\index.vue 中, 添加 JS 代码如下:
<template> </template><script>import api from '@/api/category'
export default {
data() { return {list: [], page: { // 分页相关total: 0, // 总记录数 current: 1, // 当前页码 size: 20, // 每页显示20条数据, },query: {} // 查询条件} },// 钩子函数获取数据 created () {this.fetchData() },methods: {async fetchData() {const { data } = await api.getList(this.query,this.page.current,this.page.size);this.list = data.records;this.page.total = data.total;},}</script>
列表模板
- 修改 src\views\category\index.vue ,编写模板代码:
<el-table>
列表参考:https://element.eleme.cn/#/zh-CN/component/table 链接: link.
<template><div><!-- 表格 --><el-table stripe :data="list" border style="width: 100%"><el-table-column align="center" width="60px" type="index" label="序号"></el-table-column><el-table-column align="center" prop="name" label="分类名称"></el-table-column><el-table-column align="center" prop="sort" label="排序"></el-table-column><el-table-column align="center" prop="remark" label="备注"></el-table-column><el-table-column align="center" prop="status" label="状态"><template slot-scope="scope"><el-tag :type="scope.row.status | statusFilter">{{ scope.row.status ? "正常" : "禁用" }}</el-tag></template></el-table-column><el-table-column align="center" label="操作"><template slot-scope="scope"><el-buttontype="primary"@click="handleEdit(scope.row.id)"size="mini">编辑</el-button><el-buttontype="danger"@click="handleDelete(scope.row.id)"size="mini">删除</el-button></template></el-table-column></el-table></div>
</template>
- 在
methods
选项中添加handleEdit
编辑和handleDelete
删除方法,后面需要使用。
methods: { fetchData () {
api.getList(this.query, this.page.current, this.page.size).then(response => {
// console.log(response)this.list = response.data.records this.page.total = response.data.total })},handleEdit(id) { console.log('编辑', id)},handleDelete(id) { console.log('删除', id) }, }
状态码转名称
渲染后发现状态码,我们将状态列以转为名称,并且使用 <el-tag>
标签包裹,其中通过 filters
选项来定义过滤器来实现样式转换。
<el-tag>
参考: https://element.eleme.cn/#/zh-CN/component/tag 链接: link.
- 定义
statusFilter
过滤器转换样式
export default {
filters: { statusFilter(status) {
// 样式 在这里插入代码片
const statusMap = {0: 'danger', 1: 'success'}
// status等于0返回danger, 1返回success
return statusMap[status] } },
//....
}
- 在
methods
选项中添加handleEdit
编辑和handleDelete
删除方法,后面需要使用。
methods: {
fetchData () {
api.getList(this.query, this.page.current, this.page.size).then(response => {
// console.log(response)this.list = response.data.records this.page.total = response.data.total }) },handleEdit(id) { console.log('编辑', id) },handleDelete(id) { console.log('删除', id) }, }
分页查询实现
- 修改 src\views\category\index.vue ,在 template 标签中添加分页组件:
注意:添加在div
里面。因为template
里面只能有唯一根节点
<!-- 分页组件 --><el-pagination@size-change="handleSizeChange"@current-change="handleCurrentChange":current-page="page.current":page-sizes="[10, 20, 50]":page-size="page.size"layout="total, sizes, prev, pager, next, jumper":total="page.total"></el-pagination>
methods
选项中定义handleSizeChange
每页条目数改变后触发的方法,和handleCurrentChange
页面改变后触发的方法。
methods: {
// 当每页显示条数改变后,被触发 , val是最新的每页显示条数handleSizeChange(val) { this.page.size = val this.fetchData() },// 当页码改变后,被触发 , val 是最新的页面 handleCurrentChange(val) { this.page.current = val this.fetchData()},// ... }
- 测试,查看浏览器控制台 Network 处提交数据
条件查询实现
在列表上方添加查询功能。
Form 表单参考 :https://element.eleme.cn/#/zh-CN/component/form#xing-nei-biao-dan链接: link.
Select选择器:https://element.eleme.cn/#/zh-CN/component/select 链接: link.
- 修改 src\views\category\index.vue ,增加条件查询模板代码:
<el-form :inline="true" :model="query" size="mini"> <el-form-item label="分类名称:"> <el-input v-model.trim="query.name"></el-input></el-form-item><el-form-item label="状态:" > <!-- clearable 清空按钮,filterable 是否可搜索 --><el-select v-model="query.status" clearable filterable style="width: 85px"> <el-option v-for="item in statusOptions" :key="item.code" :label="item.name" :value="item.code">
</el-option></el-select></el-form-item> <el-form-item> <el-button icon='el-icon-search' type="primary" @click="queryData">查询</el-button> <el-button icon='el-icon-refresh' class="filter-item" @click="reload">重置</el-button> <el-button type="primary" size="mini" icon="el-icon-circle-plus-outline" >新增</el- button> </el-form-item> </el-form>
- 声明一个全局变量
payTypeOptions
用于状态下拉框,并在data
选项声明与赋值payTypeOptions
属性。
<script> import api from '@/api/category' // 用于下拉框
const statusOptions = [
{code: 0, name: '禁用'},{code: 1, name: '正常'} ]export default { data() {return {list: [],page: {// 分页相关 total: 0, // 总记录数current: 1, // 当前页码 size: 20, // 每页显示20条数据,},query: {}, // 查询条件 statusOptions, //状态下拉框}},
- 在
methods
声明queryData
查询方法 , 主要是把this.page.current
当前页面变为 1
methods: {
// 查询
queryData() {
// 将页码变为第1页
this.page.current = 1 this.fetchData()},
- 重置功能:在
methods
选项中添加reload
方法,模板中触发调用此方法
methods: {
// 重置 or 刷新当前页面reload() { this.query = {} this.fetchData() },// ... }
2.新增功能
- 点击 新增 按钮后,对话框形式弹出新增窗口
- 输入分类信息后,点击 确定 提交表单数据;
新增窗口实现
新增和修改功能共用一个组件,我们将它作为子组件引入到列表查询父组件中,下面先将组件定义出来。
弹出功能参考:https://element.eleme.cn/#/zh-CN/component/dialog#zi-ding-yi-nei-rong 链接: link.
el-dialog
标答属性 title
窗口标题, visible.sync
是否弹出窗口
注意其中包含多行文本编辑框。
- 创建新增和修改的组件文件: src\views\category\edit.vue
- 定义模板代码
<template><el-dialog:title="title":visible.sync="visible"width="500px":before-close="handleClose"><el-formref="formData":model="formData"label-width="100px"label-position="right"style="width: 400px"><el-form-item label="分类名称:" prop="name"><el-input v-model="formData.name"></el-input></el-form-item><el-form-item label="状态:" prop="status"><el-radio-group v-model="formData.status"><el-radio :label="1" value="1">正常</el-radio><el-radio :label="0" value="0">禁用</el-radio></el-radio-group></el-form-item><el-form-item label="排序:" prop="sort"><el-input-numberv-model="formData.sort":min="1":max="10000"style="width: 295px"></el-input-number></el-form-item><el-form-item label="备注:" prop="remark"><el-input type="textarea" v-model="formData.remark"></el-input></el-form-item><el-form-item><el-button type="primary" @click="submitForm('formData')">确定</el-button><el-button @click="handleClose">取消</el-button></el-form-item></el-form></el-dialog>
</template>
注意:每个 el-form-item 不要少了 prop ,不然清空不了数据。
- 新增功能中引用的属性都通过父组件传递过来,下面我们将它们通过 props 声明出来,并且在
methods 中声明 handleClose 关闭弹窗和 submitForm 确定提交表单方法
<script> export default {
// 接收父组件传递的属性
props: {visible: { //弹出隐藏 type: Boolean, default: false },title: { // 标题 type: String,default: '' },
formData: {
// 表单数据type: Object, default: {} },remoteClose: Function // 用于关闭窗口
},methods: { // 关闭弹窗 handleClose(done) { },//提交表单 submitForm(formName) { },}
}
</script>
列表引用新增组件
在父组件 category/index.vue 引用 category/edit.vue 子组件实现弹窗
- 导入 edit.vue 组件,并使用
components
选项引用为子组件
<script>import api from '@/api/category'import Edit from './edit'export default {components: {Edit}, //...}</script>
- 模板中使用
<Edit>
子组件
<template> <div > <!-- 条件查询 --><!-- 数据列表 --><!-- 分页组件 --> <!-- 新增与编辑组件 --> <Edit:title="edit.title":visible="edit.visible":formData="edit.formData":remoteClose="remoteClose"/></div> </template>
- 在
data
选项中声明传递给子组件的属性、方法
<script>import api from '@/api/category'import Edit from './edit' export default {components: { Edit },data() { return { //... edit: { // 子组件中引用 title: '', visible: false,formData: {}} } },methods: { // 触发关闭弹出的新增修改子组件窗口 remoteClose() {}, } }</script>
- 为 新增 按钮绑定点击事件
@click="openAdd"
弹出窗口
<el-buttonicon="el-icon-circle-plus-outline"type="primary"@click="openAdd">新增
</el-button>
methods: {
//打开新增窗口
openAdd() {this.edit.visible = true;this.edit.title = "新增";},//... }
- 测试是否正常打开
注意: 要在el-form-item
标签的prop
属性中指定字段名, 不然有时间会输入框输入不了,如果还是输入不了,在 index.vue 组件中的edit.formData
中将字段名指定出来
data() {return { edit: { // 子组件中引用 title: '', visible: false,formData: { id: null,name: '', sort: null, remark: '' }}} }
关闭弹出窗口
当点击 取消 按钮或者右上角 X 将关闭窗口
- 错误的关闭窗口方式:
注意:不能在子组件 edit.vue 中直接将this.visible = false
关闭窗口,因为它是父组件传递过来的,子组件不能直接改。
// 关闭弹窗
handleClose(done) {
//this.visible = false错误的,因为它是父组件传递过来的,子组件不能直接改
},
- 正确的关闭窗口方式:
在edit.vue 子组件中触发 list.vue 父组件的remoteClose
方法来关闭窗口。
edit.vue 中触发父组件的remoteClose
,并重置清空表单数据
methods: {
// 关闭弹窗handleClose(done) { // 表单清空 this.$refs['formData'].resetFields() // this.visible// 错误的,因为它是父组件传递过来的,子组件不能直接改 // 因为 visible 是父组件的属性,所以要让父组件去改变值 this.remoteClose() },//提交表单 submitForm(formName) { }, }
- 在 index.vue 中将
this.edit.visiable=false
关闭窗口,刷新数据。
methods: {
//打开新增窗口openAdd() { this.edit.visible = true this.edit.title = '新增' },// 触发关闭弹出的新增修改子组件窗口 remoteClose() { // 一定要加上这个,不然有时候表单输入不了值this.edit.formData = {} this.edit.visible = false this.fetchData() }
校验表单数据
- 在 edit.vue 新增窗口的
el-form
上绑定属性:rules="rules"
<template><!--弹窗--> <el-dialog :title="title" :visible.sync="visible":before-close="handleClose"width="500px"><!-- status-icon 当表单校验不通过时, 输入框右侧有个 x 小图标 --><el-form :rules="rules"
- 在 data 选项中添加
rules
属性进行校验
data() {return {rules: {// porp值name: [{ required: true, message: "请输入分类名称", trigger: "blur" }],status: [{ required: true, message: "请输入分类名称", trigger: "change" },],sort: [{ required: true, message: "请输入分类名称", trigger: "blur" }],},};},
提交表单数据
当点击新增窗口中的确认按钮时, 提交表单数据,后台API服务接口响应新增成功或失败。
请求URL: /article/category
请求方式: post
Api 调用接口
- 在 src\api\category.js 添加调用新增接口的方法
add(data) {return request({url: `/article/category`,method: 'post',data})},
- 在 src\views\category\edit.vue 中的
submitForm
方法中判断校验是否通过,通过了则调用submitData
异步方法提交数据,代码如下:
注意: async submitData(){}
不要少了前面的 async
<script> import api from '@/api/category'
export default {
//...,
methods: {// ...
//2. 提交表单// 2.提交表单数据submitForm(formName) {this.$refs[formName].validate((valid) => {if (valid) {// 校验通过,提交表单数据this.submitData();} else {// 校验不通过return false;}});},
//3. 异步方法提交数据async submitData() {let response = null;if (this.formData.id) {//编辑response = await api.update(this.formData);} else {//新增response = await api.add(this.formData);}// 等上面返回数据response后再进行处理if (response.code === 20000) {// 提交成功, 关闭窗口, 刷新列表this.$message({showClose: true,message: "保存成功",type: "success",});// 关闭窗口this.handleClose();} else {this.$message({showClose: true,message: "保存失败",type: "error",});}},</script>
3.修改功能
当点击 编辑 按钮后,弹出编辑窗口,并查询出分类相关信息进行渲染。修改后点击 确定 提交修改后的数据。
添加查询数据
请求URL: /article/category/{id}
请求方式: get
描述:通过类别 ID 查询数据接口
添加提交修改数据
请求URL: /article/category
请求方式: put
描述:类别数据更新
Api 调用接口回显数据
- src\api\category.js 添加通过ID查询方法
getById
和 更新方法update
// 查询类别详情getById(id) {return request({url: `/article/category/${id}`,method: 'get'})},//更新update(data) {return request({url: `/article/category`,method: 'put',data})},
- 在 src\views\category\index.vue 中的
handleEdit
方法做如下修改:再特别强调下是 index.vue,不是 edit.vue
handleEdit(id) {//通过id查询详情api.getById(id).then((response) => {if (response.code === 20000) {// 将查询的详情传递this.edit.formData = response.data;this.edit.title = "编辑";this.edit.visible = true;}});},
提交修改后的数据
在 src/views/category/edit.vue 组件中的 submitData
方法加上一个判断 this.formData.id
存在则为更新,否则是新增操作。
// 提交表单数据submitForm(formName) {this.$refs[formName].validate((valid) => {if (valid) {// 校验通过,提交表单数据this.submitData();} else {// 校验不通过return false;}});},// 异步方法提交数据async submitData() {let response = null;if (this.formData.id) {//编辑response = await api.update(this.formData);} else {//新增response = await api.add(this.formData);}// 等上面返回数据response后再进行处理if (response.code === 20000) {// 提交成功, 关闭窗口, 刷新列表this.$message({showClose: true,message: "保存成功",type: "success",});// 关闭窗口this.handleClose();} else {this.$message({showClose: true,message: "保存失败",type: "error",});}},},
};
3.删除功能
当点击删除按钮后, 弹出提示框,点击确定后,执行删除并刷新列表数据
确认消息弹框参考:https://element.eleme.cn/#/zh-CN/component/message-box#que-ren-xiao-xi 链接: link.
删除接口
请求URL: /article/category/{id}
请求方式: delete
描述:根据ID删除类别
Api 调用接口
- src\api\category.js 添加
deleteById
方法
//删除deleteById(id) {return request({url: `/article/category/${id}`,//单反引号method: 'delete',// delete 方式提交})},
- 在 src\views\category\index.vue 中的
handleDelete
方法做如下修改:
// 删除
handleDelete(id) {this.$confirm('确认删除这条记录吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning'}).then(() => { // 确认api.deleteById(id).then(response => { //提示信息 this.$message({ type: response.code===20000 ? 'success':'error',message: response.message })// 刷新列表 this.fetchData() }) }).catch(() => { // 取消删除,不理会 }) }
- 检查 删除 按钮是否和下面代码一致
<el-table-column align="center" label="操作"><template slot-scope="scope"><el-buttontype="primary"@click="handleEdit(scope.row.id)"size="mini">编辑</el-button><el-buttontype="danger"@click="handleDelete(scope.row.id)"size="mini">删除</el-button></template></el-table-column>
完整代码
category/index.vue
<template><div><!-- 条件查询 --><el-form :inline="true" :model="query" size="small "><el-form-item label="分类名称"><el-input v-model="query.name" placeholder="审批人"></el-input></el-form-item><el-form-item label="状态"><el-selectv-model="query.status"clearablefilterablestyle="width: 85px"><el-option label="正常" value="1"></el-option><el-option label="禁用" value="0"></el-option></el-select></el-form-item><el-form-item><el-button icon="el-icon-search" type="primary" @click="queryData">查询</el-button><el-button icon="el-icon-refresh" @click="reload">重置</el-button><el-buttonicon="el-icon-circle-plus-outline"type="primary"@click="openAdd">新增</el-button></el-form-item></el-form><!-- 表格 --><el-table stripe :data="list" border style="width: 100%"><el-table-column align="center" width="60px" type="index" label="序号"></el-table-column><el-table-column align="center" prop="name" label="分类名称"></el-table-column><el-table-column align="center" prop="sort" label="排序"></el-table-column><el-table-column align="center" prop="remark" label="备注"></el-table-column><el-table-column align="center" prop="status" label="状态"><template slot-scope="scope"><el-tag :type="scope.row.status | statusFilter">{{ scope.row.status ? "正常" : "禁用" }}</el-tag></template></el-table-column><el-table-column align="center" label="操作"><template slot-scope="scope"><el-buttontype="primary"@click="handleEdit(scope.row.id)"size="mini">编辑</el-button><el-buttontype="danger"@click="handleDelete(scope.row.id)"size="mini">删除</el-button></template></el-table-column></el-table><!-- 分页组件 --><el-pagination@size-change="handleSizeChange"@current-change="handleCurrentChange":current-page="page.current":page-sizes="[10, 20, 50]":page-size="page.size"layout="total, sizes, prev, pager, next, jumper":total="page.total"></el-pagination><!-- 弹框 --><Edit:title="edit.title":visible="edit.visible":formData="edit.formData":remoteClose="remoteClose"/></div>
</template>
<script>
import api from "@/api/category";
import Edit from "./edit";
export default {name: "Category", //和对应路由表中配置的name值一致components: {Edit,},data() {return {query: {}, //查询条件list: [],page: {current: 1, //当前页码size: 20, //每页显示多少条total: 0, //总计录数},// statusOptions, // 状态下拉框数组edit: {title: "",visible: false,formData: {},},};},filters: {statusFilter(status) {// 0 禁用,1 正常const statusMap = { 0: "danger", 1: "success" };return statusMap[status];},},created() {this.fetchData();},methods: {fetchData() {api.getList(this.query, this.page.current, this.page.size).then((response) => {this.list = response.data.records;this.page.total = response.data.total;});},handleEdit(id) {//通过id查询详情api.getById(id).then((response) => {if (response.code === 20000) {// 将查询的详情传递this.edit.formData = response.data;this.edit.title = "编辑";this.edit.visible = true;}});},//删除handleDelete(id) {this.$confirm("确认删除这条记录吗?", "提示", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning",}).then(() => {// 发送删除请求api.deleteById(id).then((response) => {this.$message({type: response.code === 20000 ? "success" : "error",message: response.message,});});//刷新列表数据this.fetchData();}).catch(() => {//取消删除,不用理会});},//val 是切换之后的每页显示多少条handleSizeChange(val) {this.page.size = val;this.fetchData();},handleCurrentChange(val) {this.page.current = val;this.fetchData();},// 条件查询queryData() {//将页码变为1,第1页this.page.current;this.fetchData();},//重置reload() {this.query = {};this.fetchData();},// 关闭窗口remoteClose() {this.edit.formData = {};this.edit.visible = false;this.fetchData();},// 点击新增openAdd() {this.edit.visible = true;this.edit.title = "新增";},},
};
</script>
category/edit.vue
<template><el-dialog:title="title":visible.sync="visible"width="500px":before-close="handleClose"><el-form:rules="rules"ref="formData":model="formData"label-width="100px"label-position="right"style="width: 400px"><el-form-item label="分类名称:" prop="name"><el-input v-model="formData.name"></el-input></el-form-item><el-form-item label="状态:" prop="status"><el-radio-group v-model="formData.status"><el-radio :label="1" value="1">正常</el-radio><el-radio :label="0" value="0">禁用</el-radio></el-radio-group></el-form-item><el-form-item label="排序:" prop="sort"><el-input-numberv-model="formData.sort":min="1":max="10000"style="width: 295px"></el-input-number></el-form-item><el-form-item label="备注:" prop="remark"><el-input type="textarea" v-model="formData.remark"></el-input></el-form-item><el-form-item><el-button type="primary" @click="submitForm('formData')">确定</el-button><el-button @click="handleClose">取消</el-button></el-form-item></el-form></el-dialog>
</template><script>
import api from "@/api/category";
export default {props: {//弹窗标题title: {type: String,default: "",},// 弹出窗口,true弹出visible: {type: Boolean,default: false,},// 提交表单数据formData: {type: Object,default: {},},remoteClose: Function, // 用于关闭窗口},data() {return {rules: {// porp值name: [{ required: true, message: "请输入分类名称", trigger: "blur" }],status: [{ required: true, message: "请输入分类名称", trigger: "change" },],sort: [{ required: true, message: "请输入分类名称", trigger: "blur" }],},};},methods: {// 关闭窗口handleClose() {this.$refs["formData"].resetFields();// 注意不可以通过 this.visble = false 来关闭,因为它是父组件的属性this.remoteClose();},// 提交表单数据submitForm(formName) {this.$refs[formName].validate((valid) => {if (valid) {// 校验通过,提交表单数据this.submitData();} else {// 校验不通过return false;}});},// 异步方法提交数据async submitData() {let response = null;if (this.formData.id) {//编辑response = await api.update(this.formData);} else {//新增response = await api.add(this.formData);}// 等上面返回数据response后再进行处理if (response.code === 20000) {// 提交成功, 关闭窗口, 刷新列表this.$message({showClose: true,message: "保存成功",type: "success",});// 关闭窗口this.handleClose();} else {this.$message({showClose: true,message: "保存失败",type: "error",});}},},
};
</script>
<style>
</style>
api/category.js
import request from '@/utils/request'export default {//分类查询列表getList(query, current = 1, size = 20) {return request({url: `/article/category/search`,method: 'post',data: {...query,current,size}})},add(data) {return request({url: `/article/category`,method: 'post',data})},// 查询类别详情getById(id) {return request({url: `/article/category/${id}`,method: 'get'})},//更新update(data) {return request({url: `/article/category`,method: 'put',data})},//删除deleteById(id) {return request({url: `/article/category/${id}`,method: 'delete',})},// 查询类别详情getNormalList() {return request({url: `/article/category/list`,method: 'get'})},// 获取所有正常状态的分类和标签getCategoryAndLabel() {return request({url: `/article/category/label/list`,method: 'get'})},
}
这篇关于手摸手用element实现列表增删改查的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!