前后端综合案例分析(增删改查)
一、User表
(一)查询
1.在js文件夹中创建user.js文件,在user.html文件中导入axios,vue框架和user.js文件
<script src="/js/vue.js"></script>
<script src="/js/axios.min.js"></script>
<script src="/js/user.js"></script>
注意:在路径前面要加"/",斜杠代表的是根路径
注意:js文件是专门用来【写功能(方法)】的,HTML用来【写内容】,css用来【写样式】
注意:查看HTML页面是否有视图层,即
注意:在导入user.js文件的时候,要放在整个HTML页面的最后一行。在开发中,css放在前面,功能放在后面
原因:浏览器读到最后一行的时候,DOM对象才能够封装完,封装完之后功能才能够有效
特别:如果不想把user.js放在最后,我们这里导入了jQuery,把Model层和ViewModel层放在jQuery的方法中,当页面加载完之后,就会调用这个方法
$(function(){
var model = {
};
var vm = new Vue({
});
});
2.在js文件中写功能(根据给的页面模板)
注意:Model层和ViewModel层都是写在jQuery方法中的
(1)写Model层
var model = {
name:'',//根据名字搜索,定义一个name,用来做搜索框的数据
list:[],//页面有表格数据,定义一个数组,用来存表格的数据
pageSize:5,//显示每页条数,初始值是5
total:0,//显示总条数,初始值是0
pages:0,//总页数
pageNum:1,//显示页码第几页,初始值是1
user:{username:'',password:''},//需要添加一个user对象(看成一个整体,也可以定两个变量)
};
(2)写ViewModel层
var vm = new Vue({
el:'#app',
data:model,
});
(3)绑定数据:在HTML页面绑定Model层所定义的变量
注意:文本框、密码框、文本域、下拉框、单选、多选等可以修改的用v-model双向绑定
<input v-model="name" type="text" placeholder="请输入搜索关键字"/>
<select @change="getAll()" v-model="pageSize" name="copynum">
<span>总共有{{total}}条记录</span>
<input v-model="user.username" type="text" name="username" data-validate="required:请输入用户" />
<input v-model="user.password" type="password" name="password" data-validate="required:请输入密码" />
(4)在ViewModel层定义查询方法
methods:{
getAll(){
//向后台发请求查询, axios.get
//第一个参数:后台映射地址'/user/getAll',即向user后台控制层的getAll方法发请求
axios.get('/user/getAll',{
//get和delete通过键值对传参,有一个属性名: params
params:{
//后台需要传3个参数(控制层中getAll方法的三个参数)
//冒号左边的要和控制层参数相同,冒号右侧是当前对象的变量
username:this.name,
pageNum:this.pageNum,
pageSize:this.pageSize
}
//只要路径正确,就能找到后台方法;参数正确,后台就能拿到所需要的值
//调用then方法
//then()方法是异步执行。
//意思是:就是当.then()前的方法执行完后再执行then()内部的程序
//这样就避免了,数据没获取到等的问题
}).then((res)=>{
//前台向后台发请求,后台把数据返回,后台用户的集合放到表里面
//res.data是后台的对象
this.list = res.data.list;
this.total = res.data.total;
this.pageNum = res.data.pageNum;
this.pageSize = res.data.pageSize;
this.pages = res.data.pages;//后台的总页数赋值给前端模型的pages
})
},
(5)遍历表格
//遍历两个元素,一个是user对象,一个是下标index
//后台把数据赋给list这个数组,v-for开始遍历,有几个元素就几个<td>
<tr v-for="(user, index) in list">
<td>{{(pageNum-1)*pageSize + index + 1}}</td>
//这块儿的变量(username,password)一定要和后台bean实体类中的变量名一样
<td>{{user.username}}</td>
<td>{{user.password}}</td>
</tr>
(6)生命周期
原因:由于getAll方法用户不触发事件不会自动运行,放在生命周期内,vue实例创建完后自动运行
var vm = new Vue({
el:'#app',
data:model,
created:function (){
this.getAll();
},
截止目前步骤的逻辑原理:
①当我们访问用户页面的时候,会首先触发created里面的 this.getAll()这个事件,然后会调用当前vue对象的方法getAll
②axios.get向后台地址’/user/getAll’发请求,把params的三个参数传到后端
④后端返回集合数组赋值给list:this.list = res.data.list;
⑤list有了数据,刚才标签的v-for就会显示数据
注意:第一次访问页面,搜索框中什么数据都没有,他会把初始空值往后台传
附加解释:以下代码的逻辑原理
//只要路径'/user/getAll'正确,就能找到后台方法
//参数正确,后台就能从数据库拿到所需要的值
//拿到值后就返回json
axios.get('/user/getAll',{
params:{
username:this.name,
pageNum:this.pageNum,
pageSize:this.pageSize
}
(二)用户搜索分页
1.搜索功能的实现
要首先找到事件源(搜索事件按钮),点击触发,调用getAll方法
基本思路:加事件,调用getAll方法(搜索框没有添值,还是原来的null;添加了值,就发添加的值)只有搜索条件改变
//文本框加键盘事件,搜索框打上字就可以查询到
<input v-model="name" @keyup="getAll()" type="text" placeholder="请输入搜索关键字"/>
//搜索的超链接按钮,加单机事件触发getAll方法:v-on:click="getAll()"
<a v-on:click="getAll()" class="button border-main icon-search"> 搜索</a>
2.条数改变:@change=“getAll()”
//@change="getAll()",添加改变页码事件change事件,调用getAll方法
<select @change="getAll()" v-model="pageSize" name="copynum">
<option value="5">5条/页</option>
<option value="10">10条/页</option>
<option value="15">15条/页</option>
<option value="20">20条/页</option>
</select>
3.分页功能实现
(1)显示总页数
//"p of pages"自动遍历pages,比如pages=5,他就会遍历1到5
<span v-for="p of pages">
//p == pageNum,如果取出来的页p等于当前页pageNum,显示样式class="current"
//@click="getPage(p)"点击第几页,显示第几页的数据,需要传当前页页码参数p
<a @click="getPage(p)" v-if="p == pageNum" class="current">{{p}}</a>
<a @click="getPage(p)" v-else>{{p}}</a>
</span>
js页面添加一个getPage方法
getPage(p){ //把当前数据的pageNum改成参数p(点5就把5赋值给当前页)
this.pageNum = p;
this.getAll();//继续调用查询所有的方法
},
(2)上一页、下一页
//上一页就是当前页减去1,@click="getPage(pageNum-1)"
//v-show="pageNum!=1,当前页不等于1,显示上一页(当前页为首页,隐藏上一页)
<a v-show="pageNum!=1" @click="getPage(pageNum-1)">上一页</a>
//下一页就是当前页加1,@click="getPage(pageNum+1)"
//v-show="pageNum!=pages",当前页不等于最后一页,显示下一页(当前页为最后一页,隐藏下一页)
<a v-show="pageNum!=pages" @click="getPage(pageNum+1)">下一页</a>
(2)首页、尾页
//当前页是第一页
<a @click="getPage(1)">首页</a>
//当前页是最后一页
<a @click="getPage(pages)">尾页</a>
(三)用户添加修改删除
1、添加
(1)添加事件:@click=“add()”
注意:type="button"这里的type一定要是button类型
<button @click="add()" class="button bg-main icon-check-square-o" type="button"> 添加</button>
(2)js添加方法
add(){
//'/user/insert'是后台添加的方法,this.user是把user对象往后台传
axios.post('/user/insert', this.user).then((res)=>{
// res.data是后台返回的数据,类型是int类型,返回几条
//res.data == 1表示后台添加成功一条数据
if (res.data == 1) {
//后台的表添加了一条数据,表有变化,要重新查,调用getAll方法
this.getAll();
// 添加完后清空浏览器表单
this.user = {};
}
});
},
注意同时增加后端的注解:@RequestBody:前端发的json数据转换成Java对象
@RequestMapping("insert")
public int insert(@RequestBody TUser tUser){
return tUserService.add(tUser);
}
如果想把添加的数据显示在最前面:order by id desc
<select id="getAll" parameterType="string" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from t_user
where username like concat('%',#{username},'%')
order by id desc
</select>
2、修改
(1)在js文件的Model层添加一个新的对象用于修改
user2:{username:'',password:''}
(2)绑定数据
<input v-model="user2.username" type="text" name="username" data-validate="required:请输入用户" />
<input v-model="user2.password" type="password" name="password" data-validate="required:请输入密码" />
(3)修改数据要根据主键ID修改其他值,需要添加一个往后台传的id(添加的位置随便,只要在一个div区域内即可)
<input type="hidden" name="id" value="{{user2.id}}">
(4)js文件写一个编辑的方法
//传进来的u赋值给user2,u表示表格的用户对象
edit(u) {
this.user2 = u;
},
(5)[修改]超链接添加事件调用编辑方法
逻辑:用户点击修改的超链接,调用edit编辑方法,把当前user信息传进去,把user信息赋值给user2,然后再修改的表单出现user的信息,进行编辑
//edit(user)把当前用户的信息传进去进行编辑
<a @click="edit(user)" class="button border-main"><span class="icon-edit"></span> 修改</a>
(6)添加修改事件:@click=“update()”
注意:type="button"
<button @click="update()" class="button bg-main icon-check-square-o" type="button"> 修改</button>
(7)js文件写一个修改的方法
update(){
//注意:传的数据是this.user2
axios.put('/user/update', this.user2).then((res)=>{
if (res.data == 1) {
this.getAll();
}
})
},
(8)注意同时增加后端的注解:@RequestBody:前端发的json数据转换成Java对象
@RequestMapping("update")
public int update(@RequestBody TUser tUser){
return tUserService.update(tUser);
}
3、删除
(1)删除的超链接加事件调方法
//由于是根据id删除,方法的参数列表要传用户id
//点击事件,触发方法,把id传进去
<a @click="del(user.id)" class="button border-red"><span class="icon-trash-o"></span> 删除</a>
(2)js文件写一个删除的方法
del(i){
//confirm:确认按钮,有返回值,点确定返回的是true,继续运行;点取消返回的是false,不再运行
if (confirm('确定删除吗?')) {
axios.delete('/user/delete',{
params:{
//id传往后台
id:i
}
}).then((res)=>{
if (res.data == 1) {
//删除了一条,也要重新查数据,调用getAll方法
this.getAll();
}
})
}
二、Position表
1.后台开发
由于position的bean实体类中封装了部门对象,同时根据页面模板,职位信息的增删改查也包含了部门信息,因此需要查找出所有的部门信息。原始的department后台中只有根据id查询和根据名字模糊查询,且有分页、分条的条件,因此需要重新定义一个不需要任何条件就能查询出所有部门的方法:
(1)DepartmentAction接口中添加一个无需任何参数查询出所有部门的方法
@RequestMapping("getAlls")
public Object getAlls(){
Object all = departmentService.getAlls();
return all;
}
(2)DepartmentDAO
List<Department> getAlls();
(3)DepartmentService
Object getAlls();
(4)DepartmentServiceImpl
@Override
public Object getAlls() {
List<Department> list = departmentDao.getAlls();
return list;
}
(5)DepartmentDAO.xml
<select id="getAlls" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from department
</select>
2、前端js开发
注意:下列内容只说明区别于User表的部分
(1)Model层
//新增arr数组,用来储存遍历出来的部门信息
arr:[],
//由于position的bean实体类中封装了部门department,所以position对象中要加上department对象:department:{}
position:{name:'',departmentid:'',salary:'',department:{}},
(2)ViewModel层
生命周期
//由于findAll方法用户不触发事件不会自动运行,放在生命周期内,vue实例创建完后自动运行
created:function (){
this.getAll();
this.findAll();
},
methods
//新增findAll方法,调用后台的getAlls方法,用来无条件查询所有的部门信息
findAll(){
axios.get('/department/getAlls',{
}).then((res)=>{
//查询出来的数据复制到数组arr中
this.arr = res.data;
})
},
3、前端html开发
(1)表格遍历
<tr v-for="(position,index) in list">
<td style="text-align:left; padding-left:20px;"><input type="checkbox" name="id[]" value="" />
{{(pageNum-1)*pageSize+index+1}}</td>
<td>{{position.name}}</td>
<td>{{position.salary}}</td>
//由于部门信息被封装在position里面,所以得到部门的名字就要用position.department.name
<td>{{position.department.name}}</td>
</tr>
(2)部门遍历
<div class="label">
<label>所属部门:</label>
</div>
<div class="field">
<select v-model="position.departmentid" name="pid" class="input w50">
<option value="">请选择部门</option>
<option v-for="department in arr" :value="department.id">{{department.name}}</option>
</select>
</div>
三、Employee表
1.后台开发
由于employee的bean实体类中封装了职位对象,position的bean实体类中封装了部门对象,同时根据页面模板,员工信息的增删改查也包含了部门信息、职位信息,因此需要查找出所有的部门信息、职位信息。在做position表的时候,已经在后台定义了方法查询出所有部门,所以只需要在position的后台添加一个查询出所有部门的方法。但是需要注意的是:在增加和修改的时候,需要根据部门查询出所有职位,所以查询position信息需要进行级联:
(1)PositionAction接口中添加一个根据部门查询出所有职位的方法
@RequestMapping("seekAlls")
//根据部门做级联,这里传入部门id的参数,根据部门id查找该部门下所有职位信息
public Object seekAlls(@RequestParam("did") Integer did) {
Object all = positionService.seekAlls(did);
return all;
}
(2)PositionDAO
//查找职位信息的集合
List<Position> seekAlls(Integer did);
(3)PositionService
//查询所有职位
Object seekAlls(Integer did);
(4)PositionServiceImp
@Override
public Object seekAlls(Integer did) {
List<Position> list = positionDao.seekAlls(did);
return list;
}
(5)PositionDAO.xml
<!--查找出所有职位的id和name-->
<!--由于我们在上面将给position表的各个变量起了别名并做了映射,所以查询时也要通过映射的别名进行查询,不然数据库找不到数据-->
<!--parameterType="integer"方法里面有参数,要加上参数类型-->
<select id="seekAlls" parameterType="integer" resultMap="BaseResultMap">
select id pid,name pname
from position
-- 查询的条件:职位表的部门id和传入的参数did相同
where departmentid = #{did,jdbcType=INTEGER}
</select>
2.前台js开发
(1)Model层
//增加两个数组prr和arr用来储存position信息和department信息
prr:[],
arr:[],
//员工中封装了职位,职位中封装了部门,所以employee的对象中有position对象,position对象中有department对象
employee:{name:'',sex:'',photo:'',birthday:'',school:'',other:'',positionid:'',position:{department:{}}
(2)ViewModel层
methods
//添加findAll方法去查询所有的部门信息,并把后台得到的信息赋值到当前的arr数组中
findAll(){
axios.get('/department/getAlls',{
}).then((res)=>{
//查询出来的数据复制到数组arr中
this.arr = res.data;
})
},
//添加seekAll方法去查询所有的职位信息,并把后台得到的信息赋值到当前的prr数组中
seekAll(){
//position/seekAlls?did=' + this.employee.position.departmentid与postman中测试一样
//get是把传入的参数加在测试地址的后面
//加号是字符串拼接
//注意:由于添加和修改都用的同一个employee(this.employee.position.departmentid),所以需要一个初始化方法在实现功能后清空数据
axios.get('/position/seekAlls?did=' + this.employee.position.departmentid,{
}).then((res)=>{
//查询出来的数据复制到数组prr中
this.prr = res.data;
})
},