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/>'
})
src\main.js
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
}
src\mock\member.js
<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>
src\pages\Member.vue
运行效果如下图所示:
好了,到这里,整个前端的开发就结束了,请我们期待一起完成后端的开发。
git代码地址:https://github.com/carter659/spring-boot-vue-element.git
如果你觉得我的博客对你有帮助,可以给我点儿打赏,左侧微信,右侧支付宝。
有可能就是你的一点打赏会让我的博客写的更好:)
spring boot + vue + element-ui全栈开发入门——前端编辑数据对话框的更多相关文章
- 分享一个自搭的框架,使用Spring boot+Vue+Element UI
废弃,新的:https://www.cnblogs.com/hackyo/p/10453243.html 特点:前后端分离,可遵循restful 框架:后端使用Spring boot,整合了aop.a ...
- spring boot + vue + element-ui全栈开发入门——前端列表页面开发
一.页面 1.布局 假设,我们要开发一个会员列表的页面. 首先,添加vue页面文件“src\pages\Member.vue” 参照文档http://element.eleme.io/#/zh-CN ...
- koa+mysql+vue+socket.io全栈开发之前端篇
React 与 Vue 之间的对比,是前端的一大热门话题. vue 简易上手的脚手架,以及官方提供必备的基础组件,比如 vuex,vue-router,对新手真的比较友好:react 则把这些都交给社 ...
- spring boot + vue + element-ui全栈开发入门——开篇
最近经常看到很多java程序员朋友还在使用Spring 3.x,Spring MVC(struts),JSP.jQuery等这样传统技术.其实,我并不认为这些传统技术不好,而我想表达的是,技术的新旧程 ...
- spring boot + vue + element-ui全栈开发入门
今天想弄弄element-ui 然后就在网上找了个例子 感觉还是可以用的 第一步是完成了 果断 拿过来 放到我这里这 下面直接是连接 点进去 就可以用啊 本想着不用vue 直接导入连接 ...
- spring boot + vue + element-ui全栈开发入门——基于Electron桌面应用开发
前言 Electron是由Github开发,用HTML,CSS和JavaScript来构建跨平台桌面应用程序的一个开源库. Electron通过将Chromium和Node.js合并到同一个运行时环 ...
- spring boot + vue + element-ui全栈开发入门——spring boot后端开发
前言 本文讲解作为后端的spring boot项目开发流程,如果您还不会配置spring boot环境,就请点击<玩转spring boot——快速开始>,如果您对spring boot还 ...
- koa+mysql+vue+socket.io全栈开发之数据访问篇
后端搭起大体的框架后,接着涉及到的就是如何将数据持久化的问题,也就是对数据库进行 CURD 操作. 关于数据库方案, mongodb 和 mysql 都使用过,但我选用的是 mysql,原因: 目前为 ...
- 实习模块vue+java小型全栈开发(三)
实习模块vue+java小型全栈开发(三) --dx 背景 首先,先给自己一个答案:这篇博客我定义为(三),因为之前的两个模块页面,内容都是一样的,但是被改了几次需求,就一直拖着没有上传. 今天是真正 ...
随机推荐
- Spark环境搭建(四)-----------数据仓库Hive环境搭建
Hive产生背景 1)MapReduce的编程不便,需通过Java语言等编写程序 2) HDFS上的文缺失Schema(在数据库中的表名列名等),方便开发者通过SQL的方式处理结构化的数据,而不需要J ...
- Android源代码下载 “Gerrit下载源代码”
repo init -u ssh://jenkins@gerrit.y:29419/manifest -m k86A.xml 使用-m参数指定具体使用的是k86A.mxl文件 步骤1. curl ht ...
- VB中Winsock连续发送出现接收不到的异常问题解决方法
VB里面用WINSOCK进行一对多连接的TCP连接时,经常需要群发消息给所有已连接的客户端.代码类似如下: Option Explicit Dim bytMsg() As Byte Private S ...
- http 协议_DNS_域名解析 DNS 服务器_内容分发网络 CDN_缓存机制_HTML5 浏览器存储技术_cookie_sessionStorage_localStorage
TCP/IP 协议族 是按层次去划分的 应用层 决定了向用户提供应用服务时通信的活动. FTP 协议(文件传输协议)DNS(域名协议)HTTP(超文本传输协议) 传输层 提供处于网络连接中 ...
- <iframe>和<frame>区别
1.frame不能脱离frameSet单独使用,iframe可以 2.frame不能放在body中,否则不能正常显示 frame不能和body同时使用 <!--<body>--> ...
- MYSQL 导入导出数据库文件
一.从数据库导出数据库或表文件: mysqldump -u用戶名 -p密码 -d 数据库名 表名 > 脚本名; 导出整个数据库结构和数据mysqldump -h localhost -uroot ...
- 洛谷P3385 【模板】负环
题目描述 暴力枚举/SPFA/Bellman-ford/奇怪的贪心/超神搜索 寻找一个从顶点1所能到达的负环,负环定义为:一个边权之和为负的环. 输入输出格式 输入格式: 第一行一个正整数T表示数据组 ...
- 用ImageJ快速分析和处理图像
ImageJ是一款由美国国立卫生研究院(NIH)开发的软件,原名NIH Image,适用于McIntosh.Windows和Linux等系统.ImageJ旨在对图像进行更好的分析和处理,可以下载或在线 ...
- CodeForces 1143 B. Nirvana
题目 解决思路是,每个位上都是9的情况,遍历一下就可以了. #include <iostream> using namespace std; int n; int a[35]; int m ...
- LeetCode 606 Construct String from Binary Tree 解题报告
题目要求 You need to construct a string consists of parenthesis and integers from a binary tree with the ...