spring boot + vue + element-ui全栈开发入门——前端编辑数据对话框
需求
1.点击“添加”按钮,弹出录入数据的对话框窗口,并录入数据,如果数据有误则不允许提交。数据填写完毕后,点击“保存”按钮,调用http协议提交数据,提交完毕刷新页面数据。点击“取消”按钮关闭对话框。
2.点击列表中的“修改”按钮,弹出数据修改对话框窗口,功能同上。
3.点击列表中的“删除”按钮,弹出删除数据的询问窗口,功能以此类推。
一、添加
在“src\mock\member.js”中,增加模拟保存数据的方法:
adapters.push( (mockAdapter) => mockAdapter.onPost('/api/member/save').reply(req => { let promise = new Promise((resolve, reject) => { let data = req.data ? JSON.parse(req.data) : {} let result = {} if (data.name) { result.success = true result.message = '保存成功' } else { result.success = false result.message = '姓名是必填参数' } setTimeout(() => { resolve([200, result]) }, 2000) }) return promise }) )
在src\pages\Member.vue中编写添加相关的代码:
对话框的布局:
<!--对话框--> <el-dialog :title="form && form.id ? '编辑' : '新增' " :visible.sync="formVisible" :close-on-click-modal="false"> <el-form :model="form" label-width="100px" :rules="rules" ref="form"> <el-form-item label="姓名" prop="name"> <el-input v-model="form.name" /> </el-form-item> <el-form-item label="性别" prop="sex"> <el-radio-group v-model="form.sex"> <el-radio :label="1">男</el-radio> <el-radio :label="2">女</el-radio> </el-radio-group> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click.native="formVisible = false">取消</el-button> <el-button type="primary" @click.native="handleSubmit" :loading="formLoading">提交</el-button> </div> </el-dialog>
保存按钮的代码:
let handleSubmit = function() { if (this.formLoading) return this.$refs.form.validate(valid => { if (!valid) return this.formLoading = true //调用http协议 this.$axios.post('/api/member/save', this.form).then(res => { this.formLoading = false if (!res.data.success) { this.$message({ showClose: true, message: res.data.message, type: 'error' }); return } this.$message({ type: 'success', message: '保存成功!' }) //重新载入数据 this.page = 1 this.getRows() this.formVisible = false }).catch(e => this.formLoading = false) }) }
二、修改
如果完成添加功能,那么修改的功能就非常简单,只需要把handleEdit方法修改为:
let handleEdit = function(index, row) { this.form = Object.assign({}, row) this.formVisible = true }
注意的是:千万不要直接给form赋row的值,因为这样做的话,如果修改了数据但没有保存,关闭窗口的时候,列表中的数据会被误修改。Object.assign是克隆row的值,这样,form对象就是一个副本,怎么修改都没问题。
三、删除
在“src\mock\member.js”中,增加模拟删除数据的方法:
adapters.push( (mockAdapter) => mockAdapter.onGet(/\/api\/member\/remove\/\w+/).reply(req => { let promise = new Promise((resolve, reject) => { let result = { success: true, message: '删除成功' } setTimeout(() => { resolve([200, result]) }, 2000) }) return promise }) )
handleDelete的方法修改为:
let handleDelete = function(index, row) { if (this.pageLoading) return this.$confirm('此操作将永久删除该数据, 是否继续?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { this.pageLoading = true this.$axios.get('/api/member/remove/' + row.id).then(res => { this.pageLoading = false if (!res.data.success) { this.$message({ type: 'error', message: res.data.message }) return } this.$message({ type: 'success', message: '删除成功!' }) this.page = 1 this.getRows() }).catch(e => this.pageLoading = false) }).catch(e => {}) }
完整的代码如下:
// The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' import router from './router' Vue.config.productionTip = false import 'font-awesome/css/font-awesome.min.css' import ElementUI from 'element-ui' import './assets/theme/element-#0b0a3e/index.css' Vue.use(ElementUI) //开发模式开启mock.js if (process.env.NODE_ENV === 'development') { require('./mock') } import axios from 'axios' Vue.prototype.$axios = axios /* eslint-disable no-new */ new Vue({ el: '#app', router, components: { App }, template: '<App/>' })
import Mock from 'mockjs' let adapters = [] adapters.push( (mockAdapter) => mockAdapter.onPost('/api/member/loadPage').reply(req => { let promise = new Promise((resolve, reject) => { let data = req.data ? JSON.parse(req.data) : { size: 20 } let result = { rows: [], total: 10000 } for (let i = 0; i < data.size; i++) { let item = Mock.mock({ id: Mock.Random.guid(), name: Mock.Random.cname(), sex: Mock.Random.integer(1, 2), 'age|18-30': 1, date: Mock.Random.date(), address: Mock.mock('@county(true)'), }) result.rows.push(item) } setTimeout(() => { resolve([200, result]) }, 2000) }) return promise }) ) adapters.push( (mockAdapter) => mockAdapter.onPost('/api/member/save').reply(req => { let promise = new Promise((resolve, reject) => { let data = req.data ? JSON.parse(req.data) : {} let result = {} if (data.name) { result.success = true result.message = '保存成功' } else { result.success = false result.message = '姓名是必填参数' } setTimeout(() => { resolve([200, result]) }, 2000) }) return promise }) ) adapters.push( (mockAdapter) => mockAdapter.onGet(/\/api\/member\/remove\/\w+/).reply(req => { let promise = new Promise((resolve, reject) => { let result = { success: true, message: '删除成功' } setTimeout(() => { resolve([200, result]) }, 2000) }) return promise }) ) export { adapters }
<template> <section> <!--工具条--> <el-col :span="24" class="toolbar" style="padding-bottom: 0px;"> <el-form :inline="true" :model="filters"> <el-form-item> <el-input v-model="filters.query" placeholder="姓名/手机号等条件" /> </el-form-item> <el-form-item> <el-button type="primary" v-on:click="handleQuery" icon="el-icon-search">查询</el-button> </el-form-item> <el-form-item> <el-button type="primary" v-on:click="handleAdd" icon="el-icon-plus">添加</el-button> </el-form-item> </el-form> </el-col> <el-table :data="rows" style="width: 100%;overflow: auto;" :height="clientHeight" stripe border highlight-current-row v-loading="pageLoading"> <el-table-column label="注册日期" width="180"> <template slot-scope="scope"> <i class="el-icon-time"></i> <span style="margin-left: 10px">{{ scope.row.date }}</span> </template> </el-table-column> <el-table-column label="姓名" width="180" :show-overflow-tooltip="true"> <template slot-scope="scope"> <el-popover trigger="hover" placement="top"> <p>姓名: {{ scope.row.name }}</p> <p>住址: {{ scope.row.address }}</p> <div slot="reference" class="name-wrapper"> <el-tag size="medium">{{ scope.row.name }}</el-tag> </div> </el-popover> </template> </el-table-column> <el-table-column prop="sex" label="性别" width="100" align="center" :show-overflow-tooltip="true"> <template slot-scope="scope"> {{scope.row.sex===1?'男':'女'}} </template> </el-table-column> <el-table-column label="操作"> <template slot-scope="scope"> <el-button size="mini" type="primary" @click="handleEdit(scope.$index, scope.row)"><i class="el-icon-edit"></i>编辑</el-button> <el-button size="mini" type="danger" @click="handleDelete(scope.$index, scope.row)"><i class="el-icon-delete"></i>删除</el-button> </template> </el-table-column> </el-table> <!--底部--> <el-col :span="24" class="toolbar"> <el-pagination layout="prev, pager, next" @current-change="handleCurrentChange" :page-size="20" :total="total" style="float:right;"> </el-pagination> </el-col> <!--对话框--> <el-dialog :title="form && form.id ? '编辑' : '新增' " :visible.sync="formVisible" :close-on-click-modal="false"> <el-form :model="form" label-width="100px" :rules="rules" ref="form"> <el-form-item label="姓名" prop="name"> <el-input v-model="form.name" /> </el-form-item> <el-form-item label="性别" prop="sex"> <el-radio-group v-model="form.sex"> <el-radio :label="1">男</el-radio> <el-radio :label="2">女</el-radio> </el-radio-group> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click.native="formVisible = false">取消</el-button> <el-button type="primary" @click.native="handleSubmit" :loading="formLoading">提交</el-button> </div> </el-dialog> </section> </template> <script> const rules = { name: [{ required: true, message: '请输入姓名', trigger: 'blur' }], sex: [{ required: true, message: '请选择性别', trigger: 'change' }] } let data = () => { return { //页码 page: 1, //每页数量 size: 20, //总数 total: 0, //查询条件 filters: {}, //页面数据 rows: [], //页面载入状态 pageLoading: false, //列表高度 clientHeight: '100%', //表单数据 form: {}, //验证规则 rules: rules, //对话框隐藏状态 formVisible: false, //表单提交状态 formLoading: false } } let handleAdd = function() { this.form = {} this.form.sex = 1 this.formVisible = true } let handleEdit = function(index, row) { this.form = Object.assign({}, row) this.formVisible = true } let handleDelete = function(index, row) { if (this.pageLoading) return this.$confirm('此操作将永久删除该数据, 是否继续?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { this.pageLoading = true this.$axios.get('/api/member/remove/' + row.id).then(res => { this.pageLoading = false if (!res.data.success) { this.$message({ type: 'error', message: res.data.message }) return } this.$message({ type: 'success', message: '删除成功!' }) this.page = 1 this.getRows() }).catch(e => this.pageLoading = false) }).catch(e => {}) } let getRows = function() { if (this.pageLoading) return this.pageLoading = true let params = { page: this.page, size: this.size, query: this.filters.query } //调用post请求 this.$axios.post('/api/member/loadPage', params).then(res => { this.pageLoading = false if (!res.data || !res.data.rows) return //总数赋值 this.total = res.data.total this.page++; //页面元素赋值 this.rows = res.data.rows }).catch(e => this.pageLoading = false) } let handleSubmit = function() { if (this.formLoading) return this.$refs.form.validate(valid => { if (!valid) return this.formLoading = true //调用http协议 this.$axios.post('/api/member/save', this.form).then(res => { this.formLoading = false if (!res.data.success) { this.$message({ showClose: true, message: res.data.message, type: 'error' }); return } this.$message({ type: 'success', message: '保存成功!' }) //重新载入数据 this.page = 1 this.getRows() this.formVisible = false }).catch(e => this.formLoading = false) }) } let handleQuery = function() { this.page = 1 this.getRows() } let handleCurrentChange = function(val) { this.page = val this.getRows() } let initHeight = function() { this.clientHeight = (document.documentElement.clientHeight - 258) + 'px' } export default { data: data, methods: { //查询 handleQuery, //添加 handleAdd, //修改 handleEdit, //删除 handleDelete, //页数改变 handleCurrentChange, //获取分页 getRows, //初始化高度 initHeight, //提交数据 handleSubmit }, mounted: function() { window.addEventListener('resize', this.initHeight) this.initHeight() this.getRows() } } </script> <style scoped> </style>
运行效果如下图所示:
好了,到这里,整个前端的开发就结束了,请我们期待一起完成后端的开发。
git代码地址:https://github.com/carter659/spring-boot-vue-element.git
如果你觉得我的博客对你有帮助,可以给我点儿打赏,左侧微信,右侧支付宝。
有可能就是你的一点打赏会让我的博客写的更好:)
作者:刘冬.NET
博客地址:http://www.cnblogs.com/GoodHelper/
欢迎转载,但须保留版权