# SpringBoot-Vue 前后端分离开发
## 安装Vue.js
vue安装最新版本 npm install -g @vue/cli 或 yarn global add @vue/cli
Win + R 输入vue -V 或者vue -version , 出现版本号即Vue可安装完成。
继续输入vue ui(vue要3.0以上版本才行) ,启动项目,会自动跳转http://localhost:8080/页面。
然后可创建项目vue项目进行开发啦。
### IEDA导入前端工程
### IDEA启动项目
打开Terminal 输入npm run serve即可。
### 编写代码
### 新建Book.vue
<template> <div> <table> <tr> <td>编号td> <td>图书名称td> <td>作者td> tr> <tr v-for="item in books"> <td>{{item.id}}td> <td>{{item.name}}td> <td>{{item.author}}td> tr> table> {{msg}} div>template><script> export default { name:"Book", data(){ return{ msg:"Hello Vue", books:[{ id: 1 , name: '千羽', author: '千羽的编程之路' },{ id: 2 , name: '千寻', author: 'SpringBoot-Vue 前后端分离开发' },{ id: 3 , name: '小明', author: 'SpringBoot入门到精通' } ] } }, created() { const _this = this axios.get('http://localhost:8181/book/findAll').then(function(resp){ _this.books = resp.data }) } }script><style scoped="">style>
配置路由
在terminal添加axios库:vue add axios
### 新建数据库
create databases library;use databases;
导入数据
创建SpringBootTest工程
添加lombok,Spring Web,SpringData Jpa,MySQL Driver
配置yml文件
spring: datasource: url: jdbc:mysql://localhost:3306/library?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver jpa: show-sql: true properties: hibernate: format_sql: trueserver: port: 8181
创建BookHandler
package com.southwind.springboottest.controller;......@RestController@RequestMapping("/book")public class BookHandler { @Autowired private BookReposity bookReposity; @GetMapping("/findAll") public List findAll(){ return bookReposity.findAll(); }}
创建实体类Book.java
package com.southwind.springboottest.entity;import lombok.Data;import javax.persistence.Entity;import javax.persistence.Id;@Entity //类名与表名绑定@Datapublic class Book { //编写实体类 @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String name; private String author;}
解决跨域问题CrosConfig.java
package com.southwind.springboottest.config;@Configurationpublic class CrosConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS") .allowCredentials(true) .maxAge(3600) .allowedHeaders("*"); }}
创建BookReposity接口
package com.southwind.springboottest.reporesity;public interface BookReposity extends JpaRepository<Book,Integer>{}
debug测试
启动SpringboottestApplication
就可以实现前后端数据交互啦!
##实现技术:Spring Boot + Vue,使⽤ Spring Boot 进⾏后端应⽤开发,使⽤ Vue 进⾏前端应⽤开发。
# Vue + Element UI
> 先了解了一下Element(饿了么) UI,Element-Ul是饿了么前端团队推出的一款基于Vue.js 2.0 的桌面端UI框架。小编感觉它太强大了,主要你会查找和Ctrl + C,会前端开发基本上问题不大。
## Vue 集成 Element UI
前提是要安装好Element插件,
### 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
## menu 与 router 的绑定
1. 标签添加 router 属性。
2. 在⻚⾯中添加 标签,它是⼀个容器,动态渲染你选择的 router。
3. 标签的 index 值就是要跳转的 router。
## Element UI 表单数据校验
> 定义 rules 对象,在 rules 对象中设置表单各个选项的校验规则
required: true, 是否为必填项
message: 'error', 提示信息
trigger: 'blur',触发事件
> vuetest结构层次
### AddBook.vue
<template> <el-form style="width: 60%" :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm"> <el-form-item label="图书名称" prop="name"> <el-input v-model="ruleForm.name">el-input> el-form-item> <el-form-item label="作者" prop="author"> <el-input v-model="ruleForm.author">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-button @click="test()">testel-button> el-form-item> el-form>template><script> export default { data() { return { ruleForm: { name: '', author: '' }, rules: { name: [ { required: true, message: '图书名称不能为空', trigger: 'blur' } ], author:[ { required: true, message: '作者不能为空', trigger: 'blur' } ] } }; }, methods: { test(){ console.log(this.ruleForm) }, submitForm(formName) { const _this = this this.$refs[formName].validate((valid) => { if (valid) { axios.post('http://localhost:8181/book/save',this.ruleForm).then(function(resp){ if(resp.data == 'success'){ _this.$alert('《'+_this.ruleForm.name+'》添加成功!', '消息', { confirmButtonText: '确定', callback: action => { _this.$router.push('/BookManage') } }) } }) } else { return false; } }); }, resetForm(formName) { this.$refs[formName].resetFields(); } } }script>
### BookManage.vue
<template> <div> <el-table :data="tableData" border style="width: 70%"> <el-table-column fixed prop="id" label="编号" width="150"> el-table-column> <el-table-column prop="name" label="图书名" width="120"> el-table-column> <el-table-column prop="author" label="作者" width="120"> el-table-column> <el-table-column fixed="right" label="操作" width="100"> <template slot-scope="scope"> <el-button @click="edit(scope.row)" type="text" size="small">修改el-button> <el-button @click="deleteBook(scope.row)" type="text" size="small">删除el-button> template> el-table-column> el-table> <el-pagination background layout="prev, pager, next" :page-size="pageSize" :total="total" @current-change="page"> el-pagination> div>template><script> export default { methods: { deleteBook(row){ const _this = this axios.delete('http://localhost:8181/book/deleteById/'+row.id).then(function(resp){ _this.$alert('《'+row.name+'》删除成功!', '消息', { confirmButtonText: '确定', callback: action => {// 动态刷新 window.location.reload() } }) }) }, edit(row) { this.$router.push({ path: '/update', query:{ id:row.id } }) }, page(currentPage){ const _this = this axios.get('http://localhost:8181/book/findAll/'+currentPage+'/6').then(function(resp){ console.log(resp) _this.tableData = resp.data.content _this.pageSize = resp.data.size _this.total = resp.data.totalElements }) } }, data() { return { pageSize:'1', total:'11', tableData: null } }, created() { const _this = this axios.get('http://localhost:8181/book/findAll/1/6').then(function(resp){ console.log(resp) _this.tableData = resp.data.content _this.pageSize = resp.data.size _this.total = resp.data.totalElements }) } }script>
### BookUpdate
<template> <el-form style="width: 60%" :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm"> <el-form-item label="图书编号"> <el-input v-model="ruleForm.id" readOnly>el-input> el-form-item> <el-form-item label="图书名称" prop="name"> <el-input v-model="ruleForm.name">el-input> el-form-item> <el-form-item label="作者" prop="author"> <el-input v-model="ruleForm.author">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: { id: '', name: '', author: '' }, rules: { name: [ { required: true, message: '图书名称不能为空', trigger: 'blur' } ], author:[ { required: true, message: '作者不能为空', trigger: 'blur' } ] } }; }, methods: { submitForm(formName) { const _this = this this.$refs[formName].validate((valid) => { if (valid) { axios.put('http://localhost:8181/book/update',this.ruleForm).then(function(resp){ if(resp.data == 'success'){ _this.$alert('《'+_this.ruleForm.name+'》修改成功!', '消息', { confirmButtonText: '确定', callback: action => { _this.$router.push('/BookManage') } }) } }) } else { return false; } }); }, resetForm(formName) { this.$refs[formName].resetFields(); } }, created() { const _this = this axios.get('http://localhost:8181/book/findById/'+this.$route.query.id).then(function(resp){ _this.ruleForm = resp.data }) } }script>
配置路由/router/index.js
import Vue from 'vue'import VueRouter from 'vue-router'import BookManage from '../views/BookManage'import AddBook from '../views/AddBook'import Index from '../views/Index'import BookUpdate from '../views/BookUpdate'Vue.use(VueRouter)const routes = [ { path:"/", name:"图书管理", component:Index, show:true, redirect:"/BookManage", children:[ { path:"/BookManage", name:"查询图书", component:BookManage }, { path:"/AddBook", name:"添加图书", component:AddBook } ] }, { path:'/update', component:BookUpdate, show:false }]const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes})export default router
> 后端springbootTest代码实现BookHandler.java
package com.southwind.springboottest.controller;......@RestController@RequestMapping("/book")public class BookHandler { @Autowired private BookReposity bookReposity; @GetMapping("/findAll/{page}/{size}") public Page findAll(@PathVariable("page") Integer page, @PathVariable("size") Integer size){ Pageable pageable = PageRequest.of(page-1,size); return bookReposity.findAll(pageable); } @PostMapping("/save") public String save(@RequestBody Book book ){ Book result = bookReposity.save(book); if(result != null){ return "success"; }else { return "error"; } } @GetMapping("/findById/{id}") public Book findById(@PathVariable("id") Integer id){ return bookReposity.findById(id).get(); } @PutMapping("/update") public String update(@RequestBody Book book ) { Book result = bookReposity.save(book); if (result != null) { return "success"; } else { return "error"; } } @DeleteMapping("/deleteById/{id}") public void deleteById(@PathVariable("id") Integer id){ bookReposity.deleteById(id); }}
当然,在测试每一个功能时,建议在BookReposity接口上创建一个测试类BookReposityTest,测试看看是否成功
package com.southwind.springboottest.reporesity;......@SpringBootTestclass BookReposityTest { @Autowired private BookReposity bookReposity; //测试查找所有数据 @Test void findAll(){ System.out.println(bookReposity.findAll()); } //添加测试 @Test void save(){ Book book = new Book(); book.setName("张三"); book.setAuthor("李四"); Book save = bookReposity.save(book); System.out.println(save); } @Test void findById(){ Book book = bookReposity.findById(1).get(); System.out.println(book); } //测试修改 @Test void update(){ Book book = new Book(); book.setId(12); book.setName("测试测试"); Book save = bookReposity.save(book); System.out.println(save); } //测试删除 @Test void delete(){ bookReposity.deleteById(12); }}
## 功能展示
这代码的格式我也是调了好久
原创确实不容易,麻烦关注一下,或者“点个在看”再走