在第一篇文章我们基本实现了简单的前后端分离,但是展示出来的界面太丑了,今天我使用Element UI来美化页面,同时完善代码,实现简单的增删改查
Element UI的导入
在Vue项目中,控制面板输入以下代码,安装Element UI
npm i element-ui -S
安装成功后在main.js中添加一下代码,导入Element UI组件
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
new Vue({
el: '#app',
router,
render: h => h(App)
});
页面布局
在Element官网上找到页面容器,复制代码到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 :default-openeds="['1', '3']">
<el-submenu index="1">
<template slot="title"><i class="el-icon-message"></i>导航一</template>
<el-menu-item index="1-1">选项1</el-menu-item>
<el-menu-item index="1-2">选项2</el-menu-item>
<el-menu-item index="1-3">选项3</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<el-header style="text-align: right; font-size: 12px">
</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>
</div>
</template>
<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>
主要标签说明:
-
el-container:构建整个页面框架
-
el-aside:构建左侧菜单
-
el-menu:左侧菜单内容
常用属性:
:default-openeds 默认展开的菜单,通过菜单的index值来关联
:default-active 默认选中的菜单,通过菜单的index值来关联
以上的参数必须用单引号引起来,否则不生效

-
el-submenu:可展开的菜单
常用属性:
index:菜单的下标,文本类型,不能是数值类型,值必须拿双引号引住
-
template:对应el-submenu的菜单名
-
i:设置菜单图标,通过class属性设置
-
el-menu-item-group:设置分组的

-
el-menu-item:菜单的子节点,不可再展开
常用属性:
index:菜单的下标,文本类型,不能是数值类型。值必须拿双引号引住
在控制面板输入npm run dev启动vue项目,查看当前效果

动态生成左侧菜单栏-添加用户预览菜单和添加用户菜单
在components中添加AddUser.vue组件,用来添加用户
<template>
<h1>添加用户界面</h1>
</template>
配置路由
import Vue from 'vue'
import Router from 'vue-router'
import app from '../App'
import user from '../components/User'
import add from '../components/AddUser'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: '用户管理',
component: app,
children:[
{
path: '/user',
name: '查看用户',
component: user
},
{
path: 'add',
name: '添加用户',
component: add
}
]
}
]
})
在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)">
<!--router:实现菜单和路由的绑定,点击菜单,跳转到相应的路由界面-->
<el-menu router>
<!--$router.options 获取路由配置文件-->
<!--$router.options.routes 获取路由配置文件中的routes数据-->
<!--:index是菜单下标,只能是文本类型,所以加一个单引号,转换为文本类型-->
<!--:key 不加这个会报错,所以就加上了-->
<el-submenu v-for="(item,index) in $router.options.routes" :index="index+''" :key="index">
<template slot="title">{{item.name}}</template>
<!--:index="item2.path" 菜单与路由进行绑定-->
<!--:class="$route.path==item2.apth?'is-active':''" route.path是当前浏览器的地址,若当前浏览器的地址等于菜单的地址,则这个菜单高亮-->
<el-menu-item v-for="(item2,index2) in item.children" :index="item2.path" :key="index2" :class="$route.path==item2.apth?'is-active':''">{{item2.name}}</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<el-header style="text-align: right; font-size: 12px">
</el-header>
<el-main>
<!--展示其他路由界面-->
<router-view></router-view>
</el-main>
</el-container>
</el-container>
</div>
</template>
此时查看界面发现页面嵌套了


1、在component中新建一个Index.vue,此vue只有一个功能,那就是显示其他路由
<template>
<router-view></router-view>
</template>
2、在路由中注册Index组件,把主页显示的组件设置为Index


用户查看界面
在User.vue中添加表格组件和分页组件,限制每页显示5条数据。此时,就需要按照页数来查找数据,而不是一股脑把数据都查出来
Boot项目中编写根据页数查询数据的持久层接口、映射语句、控制层方法
public List<User> findByPages(Integer page);
<select id="findByPages" resultType="user" parameterType="int">
select * from user limit #{pages},5;
</select>
@GetMapping("/findByPages/{pages}")
public List<User> findByPages(@PathVariable("pages") Integer pages){
//开始索引=(当前页码数-1)*每页显示的数量
return dao.findByPages((pages-1)*5);
}
User.vue在初始化完成后加载第一页的数据
//页面初始化完成后要加载的东西
created() {
//this指的是当前的vue对象,把vue对象赋给_this
const _this=this
this.axios.get('http://localhost:8081/user/findByPages/1').then(function (resp) {
//回调函数中的this指的是回调
//把data数据赋给_this,即vue对象
_this.users=resp.data
})
}
给分页组件绑定事件方法,动态的查询每页的数据
<template>
<div>
<el-table
:data="users"
border
style="width: 100%">
<el-table-column
fixed
prop="id"
label="编号"
width="200">
</el-table-column>
<el-table-column
prop="name"
label="姓名"
width="150">
</el-table-column>
<el-table-column
prop="age"
label="年龄"
width="150">
</el-table-column>
<el-table-column
label="操作"
width="200">
<template slot-scope="scope">
<el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button>
<el-button type="text" size="small">编辑</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
background
layout="prev, pager, next"
:page-size="5"
:total="50"
@current-change="page"
><!--绑定page方法-->
<!--current-change 页码改变时触发,返回当前页码-->
</el-pagination>
</div>
</template>
<script>
export default {
methods: {
page(currentPage){
const _this=this
this.axios.get('http://localhost:8081/user/findByPages/'+currentPage).then(function (resp) {
_this.users=resp.data
})
},
handleClick(row) {
console.log(row);
}
},
data(){
return {
users:[
]
}
},
//页面初始化完成后要加载的东西
created() {
//this指的是当前的vue对象,把vue对象赋给_this
const _this=this
this.axios.get('http://localhost:8081/user/findByPages/1').then(function (resp) {
//回调函数中的this指的是回调
//把data数据赋给_this,即vue对象
_this.users=resp.data
})
}
}
</script>
<style scoped>
</style>
添加用户页面
在Boot项目中编写添加用户的持久层接口、映射代码、控制层方法
public int addUser(User user);
<insert id="addUser" parameterType="user">
insert into user(id,name,age) values(null,#{name},#{age});
</insert>
@PostMapping("/addUser")
//@RequestBody 将前端传过来的json字符串转换为User对象
public String addUser(@RequestBody User user){
int count = dao.addUser(user);//返回受影响的行数
if(count>0){
return "success";//插入成功
}else{
return "error";//插入失败
}
}
AddUser.vue中的代码
<template>
<!--:model="ruleForm" 数据绑定,和下边的ruleForm进行绑定-->
<!--:rules="rules" 进行数据校验-->
<!-- ref="ruleForm" 设置一个名字,将来click事件要用到-->
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<!--prop="name" 校验规则取的是rules中的name-->
<el-form-item label="姓名" prop="name">
<!--v-model="ruleForm.name" 与ruleForm中的name进行绑定-->
<el-input v-model="ruleForm.name"></el-input>
</el-form-item>
<el-form-item label="年龄" prop="age">
<el-input v-model="ruleForm.age"></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: {
name: '',
age: ''
},
rules: {
name: [
//required 是否为必填项
//message 输出信息
//trigger 触发事件
{ required: true, message: '请输入名字', trigger: 'blur' },
],
age: [
{ required: true, message: '请输入年龄', trigger: 'blur' },
],
}
};
},
methods: {
submitForm(formName) {
const _this=this
this.$refs[formName].validate((valid) => {
if (valid) {//校验通过
this.axios.post('http://localhost:8081/user/addUser',this.ruleForm).then(function (resp) {
if(resp.data=='success'){
//插入成功,跳转到查看用户界面
_this.$router.push('/user')
}
})
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
}
}
}
</script>
修改用户信息
思路分析:
1、在用户列表中点击某一用户的修改按钮后,则会携带当前用户的信息跳转到用户更新界面
2、用户修改完成之后,跳转到用户列表
在User.vue中编写携带用户编号跳转页面的方法

edit(row) {
//点击修改按钮之后,带参数跳到修改界面
this.$router.push({
path: '/update',
//query是固定的,必须写
//参数写在query里边
query: {
id: row.id
}
})
}
新建UpdateUser.vue项目,并在路由配置文件中注册

UpdateUser页面初始化完成之后,应该将要更新的数据显示在表单上
先在Boot项目中写一套根据Id查询用户的方法
public User findById(Integer id);
<select id="findById" resultType="user" parameterType="int">
select * from user where id=#{id};
</select>
@GetMapping("/findById/{id}")
public User findById(@PathVariable("id") Integer id){
return dao.findById(id);
}
在UpdateUser.vue项目的created()方法中调用根据id查询用户的方法,获得数据
//页面初始化完成后,应该根据id查出用户信息,显示在表单中
//拿参数,选择route
//跳转,选择router
created() {
const _this=this
this.axios.get('http://localhost:8081/user/findById/'+this.$route.query.id).then(function (resp) {
_this.ruleForm=resp.data
})
}
在Boot项目中编写更新用户数据的接口,修改完毕后调用此接口进行数据更新
public int updateUser(User user);
<update id="updateUser" parameterType="user">
update user set name=#{name},age=#{age} where id=#{id};
</update>
@PostMapping("/updateUser")
public String updateUser(@RequestBody User user){
int count = dao.updateUser(user);
if(count>0){
return "success";
}else{
return "error";
}
}
UpdateUser.vue的总代码
<template>
<!--:model="ruleForm" 数据绑定,和下边的ruleForm进行绑定-->
<!--:rules="rules" 进行数据校验-->
<!-- ref="ruleForm" 设置一个名字,将来click事件要用到-->
<el-form :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>
<!--prop="name" 校验规则取的是rules中的name-->
<el-form-item label="姓名" prop="name">
<!--v-model="ruleForm.name" 与ruleForm中的name进行绑定-->
<el-input v-model="ruleForm.name"></el-input>
</el-form-item>
<el-form-item label="年龄" prop="age">
<el-input v-model="ruleForm.age"></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: '',
age: ''
},
rules: {
name: [
//required 是否为必填项
//message 输出信息
//trigger 触发事件
{ required: true, message: '请输入名字', trigger: 'blur' },
],
age: [
{ required: true, message: '请输入年龄', trigger: 'blur' },
],
}
};
},
methods: {
submitForm(formName) {
const _this=this
this.$refs[formName].validate((valid) => {
if (valid) {//校验通过
this.axios.post('http://localhost:8081/user/updateUser',this.ruleForm).then(function (resp) {
if(resp.data=='success'){
//插入成功,跳转到查看用户界面
_this.$router.push('/user')
}
})
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
}
},
//页面初始化完成后,应该根据id查出用户信息,显示在表单中
//拿参数,选择route
//跳转,选择router
created() {
const _this=this
this.axios.get('http://localhost:8081/user/findById/'+this.$route.query.id).then(function (resp) {
_this.ruleForm=resp.data
})
}
}
</script>
删除用户信息
给删除按钮绑定事件

@click="del(scope.row)"
在Boot项目中编写根据id删除的方法
public int deleteUser(Integer id);
<delete id="deleteUser" parameterType="int">
delete from user where id=#{id};
</delete>
@GetMapping("/deleteUser/{id}")
public String deleteUser(@PathVariable("id") Integer id){
int count = dao.deleteUser(id);
if(count>0){
return "success";
}else{
return "error";
}
}
在User.vue中编写删除方法
del(row) {
this.axios.get('http://localhost:8081/user/deleteUser/'+row.id).then(function (resp) {
if(resp.data=='success'){
//删除成功,刷新此页面
window.location.reload()
}
})
}
最后还有一个小问题,左侧菜单栏多了一个无名的一级菜单

这是在动态生成菜单时,把更新用户的路由也生成了菜单。但实际上我们并不想要这个菜单。我们可以在路由中添加一个show属性,来设置此路由是否会生成菜单

v-if="item.show"
若路由的show属性为true,则生成菜单;否则不生成。
总结
到这里,一个简单的SpringBoot+Vue的前后端分离的简单示例就完成了。其中还有不完善的地方,请大家多多批评指教,我们一起进步。
源码链接:
链接:pan.baidu.com/s/1rMMejxxR… 提取码:ycph