Vue项目前后端交互

一,查询所有用户

1.提交方式

对于初学者来说,一般知道的提交方式就是form表单中的get/post两种提交方式,而在Controller中无论是增删查改,都统一使用@RequestMapping(“http://…”),当然这些都是正确的,也没什么问题;在使用axios来提交数据时,就不需要使用表单,那么axios则是通过get/post/put/delete来提交到指定的网址,为什么会出现这么多?其实也是规范问题,一般情况下:
get: 获取数据(查)
post:添加数据(增)
delete:删除数据(删)
put:更改数据(改)
在控制层也有相对应的xxxMapping()与之对应,这样使自己写的方法的功能一目了然。

2.查询方式

一般常用的查询方式:根据主键id查询,根据具体字段或多个字段查询。

2.1 根据主键id查询

只需在指定地址传入id即可

 /**
     * URL http://loaclhost:8082/axios/getUserById?id=1
     * 参数:id=1
     * 返回值:User
     */
    @GetMapping("getUserById")
    public User getUserById(Integer id) {
        return userService.findUserById(id);
    }

值得注意的是,因为本项目不是通过表单提交数据的,那么网址中?id=1怎么实现,即如何将你要的id通过网址传给后端,因为使用的axios,这里最常用也是最好理解的方式就是 ‘拼接’ ,没错,就是java字符串的拼接方法

axios.get("findUserById?id="+id)

2.2 根据具体字段查询

当然,也可以使用如上拼接的方法进行拼接,但这数据多了,就会显得繁琐,一两个无所谓,100个?这里,我们通常是将数据封装成对象,在前端封装成js对象,然后再传到后端用对象接收
值得注意的是用js写的格式

/**
	* 需求3:查询name="王昭君" sex="女" age=19
	* 参数语法:
	* 	数据结构:{}
	* 	关键字key(固定写法):params
	*   value: 用户需要传递的值
	*/
	let user = {
		 name:"王昭君",
		 sex:"女",
		 age:19
	}
	let url3 = "http://localhost:8082/axios/getUser"
	axios.get(url3,{params:user})
/**
     * GET测试3:利用对象的方式接受参数
     * URL:http://localhost:8082/axios/getUser?name=xx&sex=xx&age=xx
     * 参数:name/age/sex
     * 返回值:List<User>
     */
    @GetMapping("getUser")
    public List<User> getUser(User user) {
        return userService.getUserByNSA(user);
    }

也主要是因为MP会自动将对象中不为null的属性作为where条件

2.3 restFul风格

什么是restFul,说白了就是地址值不是?name=xxx&age=xxx,而是换成了/name/age,格式简单,字符大幅减少,一般用于get请求中,注意,这里是一般,也会用于其他请求方式,下面会碰到。注意,这里的拼接使用``符号,而不是""符号,同时,这里你传入的属性值需要使用${}方式括起来,前面的地址也一般不能出现动词。

/**
			* GET方式2:利用resuFul查询数据
			* 需求:查询sex=女 age>18
			* 历史原因:resuFul结构越来越受欢迎,则拼接resuFul结构 变得繁琐
			* 模板字符串:
			* 		语法:一段反引号``
			* 		取值:${key} 形式取值
			* 		优势:保留代码的格式
			*/
		   let sex2 = "女"
		   let age2 = 10
		   //let url2 = "http://localhost:8082/axios/user/"+sex2+"/"+age2
		   let url2 = `http://localhost:8082/axios/user/${sex2}/${age2}`
		   axios.get(url2).then(promise=>{
			   console.log(promise.data)
		   })

上述代码中可以看到,还有一种常见的拼接方式是let url2 = "http://localhost:8082/axios/user/"+sex2+"/"+age2
传入参数过多,不建议使用,比较麻烦。

js中与一般非常不同,在后端中一样需要特殊的操作,所以需要特别记忆一下
如果是单独的字段

/**
     * 后端服务器接收规则:
     *     1.参数与参数之后使用/分隔
     *     2.参数的位置一旦确定,一般不变
     *     3.接收的参数使用{形参变量}
     *     4.使用@PathVariable接收
     *     5.如果参数有多个建议使用对象接收 参数必须与属性一致 springMVC自动封装
     * 注意事项: 如果名称不同意,则需要转化 具体如下:
     *          @PathVariable("name") String username
     * URL: http://localhost:8082/user/貂蝉/10
     * 参数: name/age
     * 返回值: List<User>
     */
    //说明: restFul写法1
    @GetMapping("user/{name}/{age}")
    public List<User> findUserByNA(@PathVariable("name") String name,
                                   @PathVariable Integer age) {
        return userService.findUserByNA(name,age);
    }

同样也支持将字段封装成类

 	@GetMapping("user2/{name}/{age}")
    public List<User> findByNameAndAge(User user) {
        return userService.findByNameAndAge(user);
    }

restFul相同的地址,可以被不同的请求使用

3.业务实现

首先在前端的js中用axios设置好地址,然后这里需求的业务的是,你打开这个页面就要显示这些数据,如何实现呢?这就涉及到生命周期了!

3.1生命周期

流程:(偷的大佬的图QAQ)
在这里插入图片描述
知识梳理:

1.生命周期函数的方法名称 必须固定.
2.生命周期函数是VUE对象特有的函数.应该放到根目录下.
3.当页面渲染成功之后, 一共执行了4个生命周期方法.
	第一类: VUE对象的创建.
		beforeCreate:对象创建前调用
		created: VUE对象已经创建完成之后调用	
	第二类: VUE对象的挂载(渲染)
		beforeMount:  el : "#app",VUE对象在找到@APP标签之前先执行该函数.
		mounted: 当挂载完成(渲染完成),用户可以看到页面数据之后调用该函数			
4.用户修改阶段:
	第三类:
		beforeUpdate: 当用户修改数据 点击"回车" 之后调用该函数
					过渡: 数据已经被修改
		updated: 数据已经被修改之后调用该函数
5.销毁阶段:
	销毁函数,VUE对象默认不会调用. 可以通过函数由用户调用
		beforeDestroy: 在销毁方法执行前
		destroyed:     标志着VUE对象已经销毁.

所以这里我们根据需求,显然需求在created时调用方法

3.2 回调函数数据的接受以及填充中v-mode和v-text的区别

一开始我的想法很简单,返回的数据是List,那我建一个列表与接不就好了,后来问题就来了,返回数据中列表中是对象,那我是否需要在列表里定义一下对象属性值?这显然是行不通的,查阅了各种资料,是我多虑了,js是弱语言,你创建一个就行,给个名称,他什么都敢接,当然,这里为了规范,还是创建的列表
一开始,双向绑定嘛,想都没有v-model,结果呢?数据没显示出来,但是数据有43条,表确实是43条,真的很奇怪。后来查阅了下,我大概理解了一下(个人理解):
v-model:用于那种你可以改变的位置,比如文本框啊,单选按钮啊等等
v-text: 填充哪些你只能填充,但是不能改变的地方,就比如这里,你向表里填充数据,但你仅仅只能是填充,而不能对表里的数据进行更改。
代码如下:
在methods方法中

//获取所有用户信息
getUserList() {
	axios.get("findAll")
		 .then(promise=>{
			this.userList = promise.data
		})
	},
//生命周期创建完vue对象之后调用
created() {
	this.getUserList()
}

二,添加用户

1.添加方式

添加操作玩不出什么花来,就是将数据封装成对象,然后插入就好,但是这里有个非常需要注意的点,在js中需要这样的方式传数据

axios.post("addUser",this.user)

在后端同样也有一个非常重要的点,就是要把前端传过来的json对象装换为这里的user对象,具体方法如下:

/**
     * 需求:实现用户的入库操作
     * URL:http://localhost:8082/axios/saveUser
     * 参数:{name: "小燕子", age: 18, sex: "女"}
     * @param user
     * @return String 新增成功
     * 难点:
     *      json 互转 user对象
     *      1.user对象可以转化为json @ResponseBody
     *      2.json转化为user对象    @RequestBody
     *      ***只有数据data是json,url不是
     */
    @PostMapping("saveUser")
    public String saveUser(@RequestBody User user) {
        userService.saveUser(user);
        return "添加成功";
    }

这里,可能就有机智的朋友要问了,你查询的数据的时候不也是封装成对象了?怎么没提到要转了?没错,我就是那个机制的朋友,先话不多说,先看前端页面检查页面下的network
在这里插入图片描述
在这里插入图片描述
第一张图是查询,第二张是添加,其实,使我把json对象和地址弄混了,查询中用{params : this.user}的方式将对象其实就解析到地址上了,就是我们常见的?id=x&name=x…的形式,由于后端的标签是可以解析出地址中的数据,所以不用自己转对象;而添加不同,添加是将这些data数据变成json传给后端的,所以后端需要转。这里有个概念必须弄清,那就是前后端传输的数据都是通过json的形式,后面的修改操作一样的原理。

2.业务实现

v-model双向绑定数据,封装成对象,值得一说的是,js是弱语言,所以你创个空对象,然后通过v-model user.id进行设置id属性是一样的。

//添加用户信息
addUser() {
	axios.post("addUser",this.user)
		 .then(promise=>{
		 this.user = promise.data
			 alert("数据添加成功") //弹窗显示信息
			 this.getUserList() //更新用户信息表
			 this.user = ""     //将添加文本框中数据清空
	})
},

三,修改数据

2.修改方式

2.1 根据主键id更改数据

指定主键id,将id所在的行数据需要修改的内容封装成对象,后端MP会根据对象的id作为where条件,将对象中不为null的属性进行更改操作

	@PutMapping("updateUser")
    public String updateUser(@RequestBody User user) {
        userService.updateUser(user);
        return "修改成功";
    }

2.2 根据某个或多个字段更改数据

因为根据某些特定的,id主键是不会被更改的,所以可以用封装对象中id作为where条件,而别的字段是会被更改的,你将需更改的数据封装成对象,再根据这些数据查找,显然是不可能的,数据找到都不是你想要的,更别谈修改数据了,所以我们需要把这些where条件的属性单独传输给后端,这里我们就用restFul方法来实现,当然你用,拼接的方法也可以。

let name = "小燕子"
let user2 = {
		name:"小鬼当家",
		age:18,
		sex:"男"
	}
let url2 = `http://localhost:8082/axios/updateUserByName/${name}`
axios.put(url2,user2)
	.then(promise=>{
	console.log(promise.data)
	})
/**
     * 需求:根据name修改地址
     * URL:http://localhost:8082/axios/updateUserByName/小燕子
     * 注意事项: restFul可以为对象的属性赋值
     *          注意restFul的名称不要与属性重名,否则会覆盖
     *          引发BUG
     */
    @PutMapping("updateUserByName/{whereName}")
    public String updateUserByName(@PathVariable String whereName,@RequestBody User user) {
        userService.updateUserByName(whereName,user);
        return "修改成功2";
    }

这里值得一说的就是你用传进来restFul的数据,因为restFul有封装成对象的功能,那么如果写成{name},那么这个传过来的name属性是给name,还是给user对象中的name属性?有歧义,这就会造成BUG!!!

3.业务实现

3.1 显示当前行的数据

根据当前行的id先查询数据,在一块文本框中输出当前行的数据
可以在每一行的按钮点击的函数中传入当前行id属性

<button @click="update(user.id)"><a href="#update">修改</a></button>


//将需修改的用户信息查询并填入修改处
update(id) {
	axios.get("findUserById?id="+id)
		.then(promise=>{
			this.user2 = promise.data
		})
},

3.2更改数据

这里采用第一种根据主键id更改数据的方式

//更改用户信息
updateUser() {
	axios.put("updateUser",this.user2) 
		.then(promise=>{
			alert("信息修改成功") //弹窗显示信息
			this.getUserList()   //更新用户信息表
			this.user2 = {}      //清空数据
		})
},

四,删除数据

删除操作同查询数据,就不过多讲解

五,完整代码

之前代码被拆分过去碎,故线上完整代码,后端只有控制层

1.前端代码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>重写用户案例</title>
		<style>
			button{
				margin-top: 2px;
			}
		</style>
		<script src="../js/vue.js"></script>
		<script src="../js/axios.js"></script>
	</head>
	<body>
		<div id="app">
			<div align="center">
				<h3>添加用户<a name="top"></a></h3>
				姓名:<input type="text" v-model="user.name"/><br/>
				年龄:<input type="number" v-model="user.age"/><br/>
				性别:<input type="text" v-model="user.sex"/><br/>
				<button @click="addUser"><a href="#bottom">添加</a></button>
			</div>
			<hr/>
			<div align="center">
				<h3>用户信息修改<a name="update"></a></h3>
				编号:<input type="number" v-model="user2.id" disabled="disabled"/><br/>
				姓名:<input type="text" v-model="user2.name"/><br/>
				年龄:<input type="number" v-model="user2.age"/><br/>
				性别:<input type="text" v-model="user2.sex"/><br/>
				<button @click="updateUser">修改</button>
			</div>
			<hr/>
			<div>
				<table border="1px" width="80%" align="center">
					<tr align="center">
						<th colspan="5"><h3>用户列表</h3></th>
					</tr>
					<tr align="center">
						<th>编号</th>
						<th>姓名</th>
						<th>年龄</th>
						<th>性别</th>
						<th>操作</th>
					</tr>
					<tr align="center" v-for="user in userList">
						<td v-text="user.id">101</td>
						<td v-text="user.name">嫦娥</td>
						<td v-text="user.age">18</td>
						<td v-text="user.sex"></td>
						<td width="20%">
							<button @click="update(user.id)"><a href="#update">修改</a></button>
							<button @click="deleteUser(user.id)">删除</button>
						</td>
					</tr>
				</table>
			</div>
			<div align="right">
				<a name="buttom" href="#top">返回顶部</a>
			</div>
		</div>
	</body>
	<script>
		//定义axios请求前缀
		axios.defaults.baseURL="http://localhost:8082/vue"
		const app = new Vue({
			el:"#app",
			data:{
				userList:[],
				user:{
					id:null,
					name:"",
					age:null,
					sex:""
				},
				user2:{}
			},
			methods:{
				//获取所有用户信息
				getUserList() {
					axios.get("findAll")
						 .then(promise=>{
							 this.userList = promise.data
						 })
				},
				//添加用户信息
				addUser() {
					axios.post("addUser",this.user)
						 .then(promise=>{
							 this.user = promise.data
							 alert("数据添加成功") //弹窗显示信息
							 this.getUserList() //更新用户信息表
							 this.user = ""     //将添加文本框中数据清空
						 })
				},
				//将需修改的用户信息查询并填入修改处
				update(id) {
					axios.get("findUserById?id="+id)
						 .then(promise=>{
							 this.user2 = promise.data
						 })
				},
				//更改用户信息
				updateUser() {
					axios.put("updateUser",this.user2) 
						 .then(promise=>{
							 alert("信息修改成功") //弹窗显示信息
							 this.getUserList()   //更新用户信息表
							 this.user2 = {}      //清空数据
						 })
				},
				//删除用户数据
				deleteUser(id) {
					axios.delete("deleteUser?id="+id) 
						 .then(promise=>{
							 alert("删除数据成功") //弹窗显示信息
							 this.getUserList()   //更新用户信息表
						 })
				}
			},
			//生命周期创建完vue对象之后调用
			created() {
				this.getUserList()
			}
		})
	</script>
</html>

2.后端代码(仅Controller)

package com.jt.Controller;

import com.jt.Service.UserService;
import com.jt.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("vue")
@CrossOrigin //开启跨域机制
public class VueController {
    @Autowired
    private UserService userService;
    //获取所有用户信息
    @GetMapping("findAll")
    public List<User> findAll() {
        return userService.findAll();
    }
    //添加用户信息
    @PostMapping("addUser")
    public void addUser(@RequestBody User user) {
        userService.saveUser(user);
    }
    //根据id查询用户信息
    @GetMapping("findUserById")
    public User findUserById(Integer id) {
        return userService.findUserById(id);
    }
    //修改用户数据
    @PutMapping("updateUser")
    public void updateUser(@RequestBody User user) {
        userService.updateUser(user);
    }
    //删除数据
    @DeleteMapping("deleteUser")
    public void deleteUser(Integer id) {
        userService.deleteUser(id);
    }
}

六,MP入门知识

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值