🌻🌻 目录
一、解读前后端分离
1.1 前后端不分
- 前后端不分,jsp是一个典型写法,jsp和java代码结合起来,刚开始,确实提高了开发效率,但时间长了,大伙发现jsp存在的问题,对于后端程序员来说不懂前端,
- 所以开发流程一般是这样的:前端设计页面–>后端把页面改造成jsp(把后台数据塞到jsp页面)–>后端发现问题—>页面给前端—>前端不会jsp。互相踢皮球,这种方式效率低下;
- 特别是互联网 兴起后,一套系统对应多个前端,一般除了PC端, 还有移动的、小程序等,此时前后端不分方式就不是最优的选择。
1.2 前后端分离
前后段分离是将一个单体应用分成两个独立的项目:前端应用和后端应用
spring boot+jpa+vue+element-ui+MySql
二、项目环境搭建
2.1 NodeJs 的Windows安装
2.2 前端 Vue-cli 搭建
也可参考👉🏾 二 、第一个vue-cli项目
2.3 导入到 IDE 并解释vue 目录
2.3.1 导入到 IDE
- 前端工具
Webstorm 2020
- 导入如下
- 浏览器运行
http://localhost:8080/
2.3.2 解释vue目录
build
文件夹,用来存放项目构建脚本config
中存放基本配置信息,最常用的就是端口转发node_modules
存放的是项目的所有依赖,即npm install命令下载的文件src
存放项目的源码static
用来存放静态资源index.html
首页,人口页,也是整个项目唯一的html页面package.json
中定义了项目的所有依赖,包括开发时依赖和发布时依赖
对于开发者更多操作的是src
assets
存放资产文件components
存放组件router
存放路由js文件,用于页面的跳转App.vue
是一个Vue组件,也是项目的第一个Vue组件main.js
相当于java中的main方法,是整个项目的入口js
main.js
import Vue from 'vue'
import App from './App'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
components: { App },
template: '<App/>'
})
- 在main.js中导入Vue对象
- 导入App.vue,并且命名为App
- 导入router,默认识别index.js,因此可以省略
- 所有到导入成功后,创建Vue对象,设置被绑定的节点是‘#app’,‘#app’是index.html文件中的一个div
- 将router设置到vue对象中
- 声明一个组件App,App这个组件在一开始已经导入到项目中了,但是无法直接使用,必须声明
- template中定义了页面模板,即在App组件中的内容渲染到’#app’这个div中
App.vue
<template>
<div id="app">
<img src="./assets/logo.png">
<HelloWorld/>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld'
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
- App.vue是一个vue组件,包含三部分内容:页面模板 、页面脚本 、页面样式
- 页面模板中定义了一个图片,另一个是 router-view
- 'router-view‘简单理解为路由占位符
- 页面脚本是用来实现数据初始化、事件处理等等
- 页面样式
index.js
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
}
]
})
1.路由文件,path路径,对应的组件为HelloWorld,即在浏览器地址为/时,在router-view位置显示HelloWorld组件
2.3.3 编写测试
自己创建一个 Dept.vue
👇🏾👇🏾 而后修改 index.js
Dept.vue
<template>
<table>
<tr>
<td>部门编号</td>
<td>部门名称</td>
<td>部门地址</td>
</tr>
<tr v-for="item in depts">
<td>{{item.deptno}}</td>
<td>{{item.dname}}</td>
<td>{{item.dloc}}</td>
</tr>
</table>
</template>
<script>
export default {
name: "Dept",
data:function () {
return{
msg:"Depts",
depts:[{
deptno:1,
dname:'研发部门',
dloc:'深圳'
},{
deptno:2,
dname:'测试部门',
dloc:'上海'
},{
deptno:3,
dname:'财务部门',
dloc:'北京'
}]
}
}
}
</script>
<style scoped>
</style>
index.js
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Dept from "../components/Dept";
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},{
path: '/Dept',
name: 'Dept',
component: Dept
}
]
})
刷新测试得到:
2.4 后端搭建
- 数据库的创建:
myproject
并且创建表dept
- 创建 springboot的
myproject
项目
- 修改 application.yml
server:
port: 8081
#spring的配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/myproject?useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.jdbc.Driver
username: root
password: root
jpa:
show-sql: true
properties:
hibernate:
formate_sql: true
- 根据数据库创建实体
com.zql.pojo.Dept.java
package com.zql.pojo;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.criteria.CriteriaBuilder;
/**
* @Author:Daniel
* @Version 1.0
*/
@Data
@Entity
public class Dept {
@Id
private Integer deptno;
private String dname;
private String dloc;
}
- 创建jpa接口
com.zql.repository.DeptRepository
package com.zql.repository;
import com.zql.pojo.Dept;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* @Author:Daniel
* @Version 1.0
*/
public interface DeptRepository extends JpaRepository<Dept,Integer> {
}
6.创建控制台测试
(使用下面方法可快速创建测试类 DeptRepositoryTest.java
)
package com.zql.repository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
/**
* @Author:Daniel
* @Version 1.0
*/
@SpringBootTest
class DeptRepositoryTest {
@Autowired
DeptRepository deptRepository;
@Test
void findAll(){
System.out.println(deptRepository.findAll());
}
}
7.创建浏览器测试,创建 com.zql.controller.DeptController.java
package com.zql.controller;
import com.zql.pojo.Dept;
import com.zql.repository.DeptRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @Author:Daniel
* @Version 1.0
*/
@RestController
@RequestMapping("/dept")
public class DeptController {
@Autowired
private DeptRepository deptRepository;
@RequestMapping("/findAll")
public List<Dept> findAll(){
return deptRepository.findAll();
}
}
浏览器输入 http://localhost:8081/dept/findAll
2.5 前后交互
- 安装 axios
npm install --save axios
- 解决axios不能直接使用问题
解决方法:
在main.js中添加一下代码
import axios from 'axios';//加这句引用
Vue.prototype.$http=axios;//加这句赋值
- 跨域问题
在后台解决跨域问题(创建 com.zql.config.CrosConfig .java
)
package com.zql.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @Author:Daniel
* @Version 1.0
*/
@Configuration
public class CrosConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
// .allowedOrigins("*")
.allowedOriginPatterns("*")
.allowedMethods("GET","HEAD","POST","PUT","DELETE","OPTIONS")
.allowCredentials(true)
.maxAge(3600)
.allowedHeaders("*");
}
}
浏览器刷新 http://localhost:8080/#/dept
4. 绑定后端数据
created:function() {
this.$http.get('http://localhost:8081/dept/findAll').then(resp=>{
//console.log(resp)
this.depts = resp.data;
})
}
三、Vue+element-ui(引入)
3.1 引入element-ui
1.在Vue中集成element-ui
npm i element-ui -S
2.在main.js文件中 完整引入 element 组件 :
import ElementUI from ‘element-ui’
import ‘element-ui/lib/theme-chalk/index.css’
Vue.use(ElementUI)
引入Elemetn-ui布局到App.vue 解读
- Elemetn-ui布局完整代码
<el-container style="height: 500px; border: 1px solid #eee">
<el-aside width="200px" style="background-color: rgb(238, 241, 246)">
<el-menu :default-openeds="['1', '3']">
<el-submenu index="1">
<template slot="title"><i class="el-icon-message"></i>导航一</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="1-1">选项1</el-menu-item>
<el-menu-item index="1-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="1-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="1-4">
<template slot="title">选项4</template>
<el-menu-item index="1-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="2">
<template slot="title"><i class="el-icon-menu"></i>导航二</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="2-1">选项1</el-menu-item>
<el-menu-item index="2-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="2-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="2-4">
<template slot="title">选项4</template>
<el-menu-item index="2-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="3">
<template slot="title"><i class="el-icon-setting"></i>导航三</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="3-1">选项1</el-menu-item>
<el-menu-item index="3-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="3-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="3-4">
<template slot="title">选项4</template>
<el-menu-item index="3-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<el-header style="text-align: right; font-size: 12px">
<el-dropdown>
<i class="el-icon-setting" style="margin-right: 15px"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>查看</el-dropdown-item>
<el-dropdown-item>新增</el-dropdown-item>
<el-dropdown-item>删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<span>王小虎</span>
</el-header>
<el-main>
<el-table :data="tableData">
<el-table-column prop="date" label="日期" width="140">
</el-table-column>
<el-table-column prop="name" label="姓名" width="120">
</el-table-column>
<el-table-column prop="address" label="地址">
</el-table-column>
</el-table>
</el-main>
</el-container>
</el-container>
<style>
.el-header {
background-color: #B3C0D1;
color: #333;
line-height: 60px;
}
.el-aside {
color: #333;
}
</style>
<script>
export default {
data() {
const item = {
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
};
return {
tableData: Array(20).fill(item)
}
}
};
</script>
- 引入后代码显示:
- 开启浏览器显示:
http://localhost:8080/#/
- 修改后的页面显示 (删除多余的)
- element-ui后台管理系统主要标签:
- el-container 构建页面框架
- el-aside 构建左侧菜单
- el-menu 左侧菜单内容,常用属性
:default-openeds=“[‘1’, ‘3’]” 默认展开的菜单
:default-active="‘1-1’"默认选中的菜单
- el-submenu 可展开的菜单,常用属性:
index=“1” 菜单的下标,文本类型,不能是数值类型。
- template:对应 el-submenu 的菜单名
- i标签 class=“el-icon-message” 设置菜单图标
3.2 修改引入页面显示
- 在 components下面分别创建
PageOne.vue,PageTwo.vue
- 在 components下面创建
Index.vue
将上面导入的 ui复制过来做动态展示
<template>
<div >
<el-container style="height: 500px; border: 1px solid #eee">
<el-aside width="200px" style="background-color: rgb(238, 241, 246)">
<el-menu :default-openeds="['1', '2']">
<!--<el-submenu index="1">
<template slot="title"><i class="el-icon-message"></i>导航一</template>
<el-menu-item-group>
<el-menu-item index="1-1">选项1</el-menu-item>
<el-menu-item index="1-2">选项2</el-menu-item>
</el-menu-item-group>
</el-submenu>-->
<!--动态加载菜单-->
<el-submenu v-for="(item,index) in $router.options.routes" :index="+'' ">
<template slot="title"><i class="el-icon-message"></i>{{item.name}}</template>
<el-menu-item-group>
<el-menu-item v-for="(item2,index2) in item.children" :index="index+'-'+index2">{{item2.name}}</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<el-header style="text-align: right; font-size: 12px">
<el-dropdown>
<i class="el-icon-setting" style="margin-right: 15px"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>查看</el-dropdown-item>
<el-dropdown-item>新增</el-dropdown-item>
<el-dropdown-item>删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<span>王小虎</span>
</el-header>
<el-main>
<router-view/>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
export default {
name: "Index"
}
</script>
<style scoped>
</style>
- App.vue则变动如下
- 修改路由 index.js
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Dept from "../components/Dept";
import PageOne from "../components/PageOne";
import PageTwo from "../components/PageTwo";
import App from "../App";
import Index from "../components/Index";
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: '导航一',
component: Index,
children:
[
{
path: '/PageOne',
name: '页面一',
component: PageOne
},{
path: '/PageTwo',
name: '页面二',
component: PageTwo
}
]
}
]
})
- 最终动态展示的页面如下:
四、菜单和路由动态绑定
4.1 菜单和路由动态绑定
4.2 选中菜单变色
4.3 默认展开显示页面一
最终显示: