Springboot+Vue简单Demo教程
技术实现根据 楠哥 项目做得笔记…Springboot + Vue (用的Mybatis)使用Springboot进行后端应用开发,使用Vue进行前端应用开发创建Vue工程cmd命令行创建vue工程 vue ui如果没有反应 可以查看 vue -h是否有vue ui命令 如果没有说明版本太低进行脚手架的升级 cnpm i -g @vue/cli选择目录新建项目创建项目名–关闭初始化git仓库–手动
技术实现
根据 楠哥 项目做得笔记…
Springboot + Vue (用的Mybatis)
使用Springboot进行后端应用开发,使用Vue进行前端应用开发
创建Vue工程
cmd命令行创建vue工程 vue ui
如果没有反应 可以查看 vue -h是否有vue ui命令 如果没有说明版本太低进行脚手架的升级 cnpm i -g @vue/cli
选择目录新建项目
创建项目名–关闭初始化git仓库–手动配置项目–Router、Vuex打开以及Linter/Formatter关闭–Use history mode for router? 打开 – 创建项目,不保存预设
测试
点击任务–server–启动
然后可以把服务停止了
使用IDEA导入工程
打开idea import工程
可以通过命令行运行vue
npm run serve
新建Springboot项目
由测试需要,先从数据库中某表中查询所有数据
然后测试 --成功获得数据
在Vue项目中加入axios
vue add axios
在book.vue页面使用axios获取后台数据
在模板中创建接收数据的地方
<template>
<div>
<table>
<tr>
<td>编号</td>
<td>书名</td>
<td>数量</td>
<td>鸡汤</td>
</tr>
<tr v-for="item in books">
<td>{{item.bookID}}</td>
<td>{{item.bookName}}</td>
<td>{{item.bookCounts}}</td>
<td>{{item.detail}}</td>
</tr>
</table>
</div>
</template>
以及对应的参数
重点: 后台Controller中需要加入跨域的支持
@CrossOrigin
继承ElementUI
在vue ui
可视化页面下载ElementUI插件
完成安装
在ElementUI官网使用布局
将对应代码粘贴在App.vue中
Vue + Element UI
Vue继承Element UI
Element UI 后台管理系统主要的标签
-
el-container: 用来构建整个页面的框架
-
el-aside: 构建左侧菜单栏
-
el-menu: 左侧菜单内容 常用属性
-
**:default-openeds: ** 默认展开的菜单,通过菜单的index值来关联
-
:default-active: 默认选中的菜单,通过菜单的index值来关联
-
-
el-submenu: 可展开的菜单.常用属性:
- index: 菜单的下标,文本类型,不能是数值类型
-
template: 对应el-submenu的菜单名
-
i: 设置菜单图标,通过class属性设置
-
el-icon-messae
-
el-icon-menu
-
el-icon-setting
…
-
-
el-menu-item: 菜单的子节点,不可再展开,常用属性
- index: 菜单的下标,文本类型,不能是数值类型
Vue router 来动态构建左侧菜单
- 导航1
- 页面1
- 页面2
- 导航2
- 页面3
- 页面4
在views目录下创建四个页面
配置路由
import PageOne from '../views/PageOne'
import PageTwo from '../views/PageTwo'
import PageThree from '../views/PageThree'
import PageFore from '../views/PageFore'
import APP from '../App'
Vue.use(VueRouter)
const routes = [
{
path: "/",
name: "导航1",
children: [
{
path: "/pageOne",
name: "页面1",
component: PageOne
},
{
path: "/pageTwo",
name: "页面2",
component: PageTwo
}
]
},{
path: "/navigation",
name: "导航2",
component: APP,
children: [
{
path: "/pageThree",
name: "页面3",
component: PageThree
},
{
path: "/pageFore",
name: "页面4",
component: PageFore
}
]
}
]
在APP.vue的模板上编写
<template>
<div id="app">
<el-container style="height: 500px; border: 1px solid #eee">
<el-aside width="200px" style="background-color: rgb(238, 241, 246)">
<el-menu>
<el-submenu v-for="(item,index) in $router.options.routes" :index="index">
<template slot="title"><i class="el-icon-message"></i>{{item.name}}</template>
<el-menu-item v-for="(item2,index2) in item.children" :index="index+'-'+index2">{{item2.name}}</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
<el-main>
<router-view></router-view>
</el-main>
</el-container>
</el-container>
</div>
</template>
v-for="(item,index) in $router.options.routes" :index=“index” 是为了让遍历出来的下标不一样,为了获取唯一标识
menu与router的绑定
-
标签添加router属性
-
在页面中添加标签,它是一个容器,动态渲染你选择的router
-
标签中绑定
:index="item2.path"
redirect: "/pageOne"
重定向到/pageOne页面 -
实现导航栏默认打开以及选中当前页 高亮
给加上一个判断
:class="$route.path==item2.path?'is-active':''"
$route获取的是浏览器url的当前路径地址
添加表单并实现分页查询
在ElementUI官网粘贴表单代码
<template>
<div>
<el-table
:data="tableData"
style="width: 100%"
max-height="250">
<el-table-column
fixed
prop="bookId"
label="id"
width="150">
</el-table-column>
<el-table-column
prop="bookName"
label="书名"
width="120">
</el-table-column>
<el-table-column
prop="bookCounts"
label="书本数量"
width="120">
</el-table-column>
<el-table-column
prop="detail"
label="鸡汤"
width="120">
</el-table-column>
<el-table-column
fixed="right"
label="操作"
width="120">
<template slot-scope="scope">
<el-button
@click.native.prevent="deleteRow(scope.$index, tableData)"
type="text"
size="small">
移除
</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
background
layout="prev, pager, next"
page-size="4"
:total="total"
@current-change="page">
</el-pagination>
</div>
</template>
后端使用mybatis插件pagehelper实现分页查询
-
添加pagehelper依赖
<!--mybatis分页插件--> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.3.0</version> </dependency>
-
对findAll查询方法进行修改
修改BookService接口方法
PageInfo<Book> findAll(Integer pageNum,Integer pageSize);
修改BookServiceImpl实现类
@Override public PageInfo<Book> findAll(Integer pageNum,Integer pageSize) { PageHelper.startPage(pageNum,pageSize); List<Book> books = bookDao.findAll(); PageInfo<Book> bookPageInfo = new PageInfo<>(books,pageSize); return bookPageInfo; }
修改BookController方法
@RestController @RequestMapping("book") @CrossOrigin //允许跨域 public class BookController { @Autowired private BookService bookService; @GetMapping("findAll/{page}/{limit}") public PageInfo<Book> findAll(@PathVariable("page") Integer page,@PathVariable("limit") Integer limit){ PageInfo<Book> books = bookService.findAll(page, limit); return books; } }
测试
完成前端页面的绑定
-
在methods中编写page方法
page(currentpage){ const _this = this; axios.get('http://localhost:8181/book/findAll/'+ currentpage +'/4').then(res=>{ _this.tableData = res.data.list; _this.total = res.data.total console.log(res.data); }) }
-
在data()中定义接收参数
data() { return { total: null, tableData: null } }
-
创建created()方法在页面加载前查询显示数据
created() { const _this = this; axios.get('http://localhost:8181/book/findAll/1/4').then(res=>{ _this.tableData = res.data.list; _this.total = res.data.total console.log(res.data); }) }
-
在表单中将接收属性改为后台传来的数据值
<el-table :data="tableData" style="width: 100%" max-height="250"> <el-table-column fixed prop="bookId" label="id" width="150"> </el-table-column> <el-table-column prop="bookName" label="书名" width="120"> </el-table-column> <el-table-column prop="bookCounts" label="书本数量" width="120"> </el-table-column> <el-table-column prop="detail" label="鸡汤" width="120"> </el-table-column> <el-table-column fixed="right" label="操作" width="120"> <template slot-scope="scope"> <el-button @click.native.prevent="deleteRow(scope.$index, tableData)" type="text" size="small"> 移除 </el-button> </template> </el-table-column> </el-table>
-
在后面添加分页代码
<el-pagination background layout="prev, pager, next" page-size="4" :total="total" @current-change="page"> </el-pagination>
-
设置分页代码的total为自己所定义的属性值以及@current-change方法
-
测试
Element UI 表单数据校验
定义rules对象, 在rules对象中设置表单各个校验规则
rules: {
name: [
{ required: true, message: '请输入活动名称', trigger: 'blur' },
{ min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
],
required: true,
是否为必填项message: '请输入活动名称'
提示信息trigger: 'blur'
触发事件
添加数据表
在Element UI官网找到合适的表单
<template>
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="图书名称" prop="bookName">
<el-input style="width: 60%" v-model="ruleForm.bookName"></el-input>
</el-form-item>
<el-form-item label="图书数量" prop="bookCounts">
<el-input style="width: 60%" v-model="ruleForm.bookCounts"></el-input>
</el-form-item>
<el-form-item label="图书鸡汤" prop="detail">
<el-input style="width: 60%" v-model="ruleForm.detail"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">提交</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
</template>
<script>
export default {
data() {
return {
ruleForm: {
bookName: '',
bookCounts: '',
detail: '',
},
//校验的规则
rules: {
bookName: [
{ required: true, message: '图书名称不能为空', trigger: 'blur' },
{ min: 3, max: 15, message: '长度在 3 到 5 个字符', trigger: 'blur' }
],
bookCounts: [
{ required: true, message: '图书数量不能为空(若没有请填写0)', trigger: 'change' }
],
detail: [
{ required: true, message: '图书鸡汤不能为空', trigger: 'change' }
]
}
};
},
methods: {
submitForm(formName) {
const _this = this;
this.$refs[formName].validate((valid) => {
if (valid) {
axios.post("http://localhost:8181/book/save",this.ruleForm).then(res=>{
if (res.data == "success"){
_this.$message({
message: '恭喜你,上传成功',
type: 'success'
});
_this.$router.push('/pageOne')
}
});
} else {
return false;
}
});
},
test(){
console.log(this.ruleForm);
},
resetForm(formName) {
this.$refs[formName].resetFields();
}
}
}
</script>
<style scoped>
</style>
-
在
<el-form>
中定义ref标签与所定义的方法和提交按钮绑定所定义的数据 -
在提交按钮添加点击事件
@click="submitForm('ruleForm')"
-
定义submitForm方法
submitForm(formName) { const _this = this; this.$refs[formName].validate((valid) => { if (valid) { axios.post("http://localhost:8181/book/save",this.ruleForm).then(res=>{ if (res.data == "success"){ _this.$message({ message: '恭喜你,上传成功', type: 'success' }); _this.$router.push('/pageOne') } }); } else { return false; } }); },
其中
axios
中post路径是调用后台数据插入的url -
后台创建插入方法
-
依次创建bookDao、bookDaoMapper.xml
void save(Book book); --------------------- <insert id="save" parameterType="Book"> insert into ssmbuild.books values (#{bookId},#{bookName},#{bookCounts},#{detail}); </insert>
-
创建bookService、bookServiceImpl实现类
Book save(Book book); -------------------------- @Override public Book save(Book book) { bookDao.save(book); return book; }
-
创建bookController方法
@PostMapping("save") //由于前段传来的是json对象需要加@RequestBody才能变成java对象 public String save(@RequestBody Book book){ Book result = bookService.save(book); if (result != null){ return "success"; }else { return "error"; } }
-
-
测试
修改数据
首先让选中的图书在修改页面显示信息
创建BookUpdate.vue
添加表单
<template>
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="图书id">
<el-input style="width: 60%" v-model="ruleForm.bookId" readonly></el-input>
</el-form-item>
<el-form-item label="图书名称" prop="bookName">
<el-input style="width: 60%" v-model="ruleForm.bookName"></el-input>
</el-form-item>
<el-form-item label="图书数量" prop="bookCounts">
<el-input style="width: 60%" v-model="ruleForm.bookCounts"></el-input>
</el-form-item>
<el-form-item label="图书鸡汤" prop="detail">
<el-input style="width: 60%" v-model="ruleForm.detail"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">提交</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
</template>
<script>
export default {
data() {
return {
ruleForm: {
bookId: '',
bookName: '',
bookCounts: '',
detail: '',
},
//校验的规则
rules: {
bookName: [
{ required: true, message: '图书名称不能为空', trigger: 'blur' },
{ min: 3, max: 15, message: '长度在 3 到 15 个字符', trigger: 'blur' }
],
bookCounts: [
{ required: true, message: '图书数量不能为空(若没有请填写0)', trigger: 'change' }
],
detail: [
{ required: true, message: '图书鸡汤不能为空', trigger: 'change' }
]
}
};
},
methods: {
submitForm(formName) {
const _this = this;
this.$refs[formName].validate((valid) => {
if (valid) {
axios.put("http://localhost:8181/book/bookUpdate",this.ruleForm).then(res=>{
if (res.data == "success"){
_this.$message({
message: '恭喜你,修改成功',
type: 'success'
});
_this.$router.push('/BookManage')
}
});
} else {
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
}
},
created() {
const _this = this;
axios.get("http://localhost:8181/book/findId/" + this.$route.query.bookId).then(res=>{
_this.ruleForm = res.data;
})
}
}
</script>
-
在BookMange页面中修改添加绑定事件
@click="edit()"
edit(row) { this.$router.push({ path: '/BookUpdate', query: { bookId:row.bookId } }) //console.log(row.bookId); //rows.splice(index, 1); }
点击按钮后将所选id传递
-
在后台创建update方法
BookDao、BookDaoMapper
void updateBook(Book book); ---------------------------- <update id="updateBook" parameterType="Book"> update ssmbuild.books set bookName = #{bookName},bookCounts = #{bookCounts},detail = #{detail} where bookID = #{bookId}; </update>
-
BookService、BookServiceImpl
Book updateBook(Book book);
-------------------------------
@Override
public Book updateBook(Book book) {
bookDao.updateBook(book);
return book;
}
-
BookController
//根据id修改数据 @PutMapping("bookUpdate") public String updateBook(@RequestBody Book book){ Book result = bookService.updateBook(book); if (result != null){ return "success"; }else { return "error"; } }
-
在Vue前台BookUpdate.vue中创建created函数
created() { const _this = this; axios.get("http://localhost:8181/book/findId/" + this.$route.query.bookId).then(res=>{ _this.ruleForm = res.data; }) }
并在文中使用
v-model
进行绑定[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-chiizNv5-1615121535629)(C:\Users\MengFei\AppData\Roaming\Typora\typora-user-images\image-20210307192329214.png)]
进行修改操作
步骤类似添加书籍
给提交按钮添加点击事件@click="submitForm('ruleForm')
定义方法
submitForm(formName) {
const _this = this;
this.$refs[formName].validate((valid) => {
if (valid) {
axios.put("http://localhost:8181/book/bookUpdate",this.ruleForm).then(res=>{
if (res.data == "success"){
_this.$message({
message: '恭喜你,修改成功',
type: 'success'
});
_this.$router.push('/BookManage')
}
});
} else {
return false;
}
});
}
删除数据
步骤同修改数据
-
给删除按钮添加点击事件
deleteBook(scope.row)
-
后台依次创建dao、daoMaper、Service、ServiceImpl、Controller
-
在BookMange.vue页面创建deleteBook方法
deleteBook(row){ const _this = this; axios.delete("http://localhost:8181/book/deleteBook/" + row.bookId).then(res=>{ _this.$alert('(' + row.bookName + ') 删除成功', '消息', { confirmButtonText: '确定', callback: action => { window.location.reload(); } }); }) }
res.data == “success”){
_this.
m
e
s
s
a
g
e
(
m
e
s
s
a
g
e
:
′
恭
喜
你
,
修
改
成
功
′
,
t
y
p
e
:
′
s
u
c
c
e
s
s
′
)
;
t
h
i
s
.
message({ message: '恭喜你,修改成功', type: 'success' }); _this.
message(message:′恭喜你,修改成功′,type:′success′);this.router.push(’/BookManage’)
}
});
} else {
return false;
}
});
}
[外链图片转存中...(img-nlImZzDT-1615121535631)]
## 删除数据
步骤同修改数据
- 给删除按钮添加点击事件`deleteBook(scope.row)`
- 后台依次创建dao、daoMaper、Service、ServiceImpl、Controller
- 在BookMange.vue页面创建deleteBook方法
```javascript
deleteBook(row){
const _this = this;
axios.delete("http://localhost:8181/book/deleteBook/" + row.bookId).then(res=>{
_this.$alert('(' + row.bookName + ') 删除成功', '消息', {
confirmButtonText: '确定',
callback: action => {
window.location.reload();
}
});
})
}
更多推荐
所有评论(0)