Vue
10. Axios 基本使用
10.1 引言
Axios
是一个异步请求技术,核心作用就是用来在页面中发送异步请求,并获取对应数据在页面中渲染 页面局部更新技术 Ajax
10.2 Axios 第一个程序
中文网站:https://www.kancloud.cn/yunye/axios/234845
安装:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
后端的环境搭建:
主启动类:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
entity:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private String id;
private String username;
private String email;
private Integer age;
private Integer phone;
}
controller:
@RestController
@RequestMapping("/user")
public class UserController {
//删除数据
@CrossOrigin //用来解决跨域问题
@DeleteMapping("delete")
public Map<String,Object> delete(String id){
Map<String,Object> map = new HashMap<>();
System.out.println("id = " + id);
map.put("success",true);
return map;
}
//保存数据
@CrossOrigin //用来解决跨域问题
@PostMapping("save")
public Map<String,Object> save(@RequestBody User user){
Map<String,Object> map = new HashMap<>();
System.out.println("user = " + user);
map.put("success",true);
return map;
}
//展示索引
@CrossOrigin //用来解决跨域问题
@GetMapping("findAll")
public List<User> findAll(String name){
System.out.println(name);
List<User> users = new ArrayList<>();
users.add(new User("21","赵云","[email protected]",18,1688312));
users.add(new User("22","赵学","[email protected]",12,3688395));
users.add(new User("23","赵彩","[email protected]",11,1523395));
return users;
}
}
yaml:
server:
port: 8989
10.2.1 GET方式的请求
//发送GET方式请求
axios.get("http://localhost:8989/user/findAll?name=阿昌").then(function (responese){
console.log(responese.data);
}).catch(function (error){
console.log(error); //请求正确的情况下没值
})
10.2.2 POST方式请求
//发送POST方式请求
axios.post("http://localhost:8989/user/save",{
username:"achang",
age:"23",
email:"[email protected]",
phone:"165534841"
}).then(function (resp){
console.log(resp.data)
}).catch(function (error){
console.log(error)
})
10.2.3 axios并发请求
并发请求
: 将多个请求在同一时刻发送到后端服务接口,最后在集中处理每个请求的响应结果
//1、创建一个查询所有的请求
function findAll(){
return axios.get("http://localhost:8989/user/findAll?name=阿昌");
}
//2、创建一个保存的请求
function save(){
return axios.post("http://localhost:8989/user/save",{
username:"achang",
age:"23",
email:"[email protected]",
phone:"165534841"
});
}
//3、并发执行
axios.all([findAll(),save()]).then(
axios.spread(function (resp1,resp2){
//【.spread】 用来将一组函数的响应结果汇总处理,回调函数的结果会以顺序放在参数1/2/3...
console.log(resp1.data);
console.log(resp2.data);
})
); //【.all】用来发送一组并发请求
Vue中集合Axios完成天气查询案例
后端代码:
@RestController
@RequestMapping("/weather")
public class WeatherController {
@GetMapping("find")
@CrossOrigin
public Map<String,String> findWeatherByCity(String name){
Map<String,String> map = new HashMap<>();
String weather = getWeather(name);
map.put("msg",weather);
return map;
}
//返回对应城市天气
public String getWeather(String name){
Map<String,String> weather = new HashMap<>();
weather.put("北京","晴转多云");
weather.put("温州","多云转晴");
weather.put("重庆","大雨转小雨");
weather.put("杭州","小到暴雨");
weather.put("天津","晴转多云");
weather.put("深圳","雾天");
return weather.get(name);
}
}
前端代码:
<body>
<div id="app">
<input type="text" v-model="cityName" @keyup.delete="shows" @keyup.enter="searchCity"> <input type="button" value="搜索" @click="searchCity"/> <br>
<span v-for="city in citys">
<a href="" @click.prevent="searchCitys(city)" >{
{city}}  </a>
</span>
<hr>
<span v-show="isShow">{
{cityName}},今天的天气是:{
{msg}}</span>
</div>
<!--引入vue-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!--引入axios-->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
citys:["北京","温州","杭州","重庆"],
cityName:"",
msg:"",
isShow:false
},
methods: {
searchCity(){
//获取输入城市的信息
console.log(this.cityName);
let appthis = this;
//发送axios请求
axios.get("http://localhost:8989/weather/find?name=" + this.cityName)
.then(function (resp){
appthis.msg=resp.data.msg;
appthis.isShow=true
}).catch(function (err){
console.log(err);
})
},
shows(){
this.isShow=false;
},
searchCitys(cityName){
this.cityName=cityName;
this.searchCity(); //函数中调用函数
}
}
});
</script>
</body>
11. Vue 生命周期
生命周期钩子
====>生命周期函数
# Vue生命周期总结
【1.初始化阶段】
beforeCreate(){ //1.生命周期中第一个函数,该函数在执行时Vue实例【仅仅完成了自身事件的绑定和生命周期函数的初始化工作,Vue实例中还没有 Data el methods相关属性】
console.log("beforeCreate: "+this.msg);
},
created(){ //2.生命周期中第二个函数,该函数在执行时Vue实例已经【初始化了data属性和methods中相关方法】
console.log("created: "+this.msg);
},
beforeMount(){//3.生命周期中第三个函数,该函数在执行时Vue将【El中指定作用范围作为模板编译】,如还没解析{
{}}
console.log("beforeMount: "+document.getElementById("sp").innerText);
},
mounted(){//4.生命周期中第四个函数,该函数在执行过程中,【已经将数据渲染到界面中并且已经更新页面】,如已经解析了{
{}}中获取的值
console.log("Mounted: "+document.getElementById("sp").innerText);
}
【2.运行阶段】
beforeUpdate(){//5.生命周期中第五个函数,该函数是【data中数据发生变化时】执行 这个事件执行时仅仅是Vue实例中data数据变化页面显示的【依然是原始数据】
console.log("beforeUpdate:"+this.msg);
console.log("beforeUpdate:"+document.getElementById("sp").innerText);
},
updated(){ //6.生命周期中第六个函数,该函数执行时data中数据发生变化,页面中数据也发生了变化 【页面中数据已经和data中数据一致】
console.log("updated:"+this.msg);
console.log("updated:"+document.getElementById("sp").innerText);
},
【3.销毁阶段】
beforeDestory(){//7.生命周期第七个函数,该函数执行时,Vue中【所有数据 methods componet 都没销毁】
},
destoryed(){ //8.生命周期的第八个函数,该函数执行时,【Vue实例彻底销毁】
}
vue结合bootstrap综合案例
1、环境搭建
- 创建一个SpringBoot工程
- 在main目录下创建bootvue文件夹,在下面引入
- bootstrap的css和fonts,
- vue的 js:
vue.min.js
【使用生产版本】 - axios:
axios.min.js
2、前端页面搭建
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户管理页面</title>
<!--引入bootstrap中的css样式-->
<link rel="stylesheet" href="./bootvue/css/bootstrap.min.css"/>
</head>
<body>
<!--导航-->
<nav class="navbar navbar-default">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">用户管理系统</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<li><a href="#">欢迎阿昌</a></li>
</ul>
</div>
</div>
</nav>
<!--中心布局-->
<div class="container-fluid">
<!--搜索框-->
<div class="row">
<div class="col-md-8 col-md-offset-1">
<form class="form-inline">
<div class="form-group">
<label for="searchName">姓名:</label>
<input type="text" class="form-control" id="searchName">
</div>
<div class="form-group">
<label for="searchEmail">邮箱:</label>
<input type="text" class="form-control" id="searchEmail">
</div>
<button type="submit" class="btn btn-info">搜 索</button>
</form>
</div>
</div>
<div class="row" style="margin-top: 20px">
<div class="col-md-8">
<table class="table table-striped table-hover table-bordered">
<tr>
<th>ID</th>
<th>姓名</th>
<th>年龄</th>
<th>薪资</th>
<th>电话号码</th>
<th>操作</th>
</tr>
<tbody>
<tr>
<td>1</td>
<td>郑婷婷</td>
<td>14</td>
<td>2300</td>
<td>110</td>
<td><button class="btn btn-danger">删除</button> <button class="btn btn-primary">修改</button></td>
</tr>
<tr>
<td>2</td>
<td>老李</td>
<td>15</td>
<td>2300</td>
<td>110</td>
<td><button class="btn btn-danger">删除</button> <button class="btn btn-primary">修改</button></td>
</tr>
</tbody>
</table>
</div>
<div class="col-md-4">
<form>
<div class="form-group">
<label for="username">姓名</label>
<input type="text" class="form-control" id="username" placeholder="请输入姓名">
</div>
<div class="form-group">
<label for="age">年龄</label>
<input type="text" class="form-control" id="age" placeholder="请输入年龄">
</div>
<div class="form-group">
<label for="salary">薪资</label>
<input type="text" class="form-control" id="salary" placeholder="请输入薪资">
</div>
<div class="form-group">
<label for="phoneNumber">电话号码</label>
<input type="text" class="form-control" id="phoneNumber" placeholder="请输入电话号码">
</div>
<button type="submit" class="btn btn-primary">提交</button>
<button type="submit" class="btn btn-danger">重置</button>
</form>
</div>
</div>
</div>
<!--<img src="./bootvue/IMG_0713.JPG" width="800" height="500">-->
<!--引入Vue js-->
<script src="./bootvue/js/vue.min.js"></script>
<!--引入axios js-->
<script src="./bootvue/js/axios.min.js"></script>
</body>
</html>
3、搭建mysql库表
CREATE TABLE t_user(
id VARCHAR(40) PRIMARY KEY,
NAME VARCHAR(40),
age INT(3),
salary DOUBLE(7,2),
phoneNumber VARCHAR(11)
);
随便写入一条数据:
4、引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
<scope>provided</scope>
</dependency>
<!--druid数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.17</version>
</dependency>
5、yaml配置文件
server:
port: 6161
servlet:
context-path: /users #项目名
spring:
application:
name: user #应用名【在单体架构中没有意义,在微服务系统中代表着该服务系统的唯一标识】
datasource:
type: com.alibaba.druid.pool.DruidDataSource #使用德鲁伊数据库连接池
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/bootvue?characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false
username: 'root'
password: '00000'
mybatis:
mapper-locations: classpath:com.achang.mapper/*.xml
type-aliases-package: com.achang.entity #指定bean对象包
6、SpringBoot和MyBatis整合
- dao
public interface UserDao {
//查询所有
List<User> findAll();
}
- entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Accessors(chain = true)//打开链式调用
public class User {
private String id;
private String name;
private Integer age;
private Double salary;
private String phoneNumber;
}
- 主启动类
@SpringBootApplication
@MapperScan("com.achang.dao") //mybatis包扫描
public class VueApplication {
public static void main(String[] args) {
SpringApplication.run(VueApplication.class, args);
}
}
- UserDao.xml
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.achang.dao.UserDao">
<!--查询所有-->
<select id="findAll" resultType="User">
select id,name,age,salary,phoneNumber from t_user
</select>
</mapper>
- 测试
@SpringBootTest(classes = VueApplication.class)
public class TestUserDao {
@Autowired
private UserDao userDao;
@Test
void testFindAll(){
List<User> userList = userDao.findAll();
for (User user : userList) {
System.out.println(user);
}
}
}
这里springboot和mybatis整合就算好了
7、service层和controller层
- UserService接口
public interface UserService {
//查询所有用户
public List<User> findAll();
}
- UserServiceImpl
@Service
@Slf4j
@Transactional //控制事务
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public List<User> findAll() {
return userDao.findAll();
}
}
- UserController
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
//查询所有
@CrossOrigin //允许可以跨域操作,解决Vue静态页面访问的跨域问题
@GetMapping("/findAll")
public List<User> findAll(){
List<User> userList = userService.findAll();
return userList;
}
}
- 测试
访问:http://localhost:6161/users/user/findAll
8、user.html页面的axios异步请求发送测试
created(){
//发送查询所有用户信息的操作
axios.get("http://localhost:6161/users/user/findAll").then(function (resp) {
console.log(resp);
}).catch(function (err) {
console.log(err);
});
}
- 打开页面,在vue声明周期的create()阶段发送异步请求
发现拿到了数据,测试通过
9、查询所有功能
修改代码让前端页面获取到后端发来的数据
//生命周期相关的函数
created(){
//保存this的值,在axios中的this已经是window类型了,不再是原来的了
let _app = this;
//发送查询所有用户信息的操作
axios.get("http://localhost:6161/users/user/findAll").then(function (resp) {
_app.users = resp.data;
}).catch(function (err) {
console.log(err);
});
}
- 添加数据在测试页面是否会遍历我们查询来的所有数据
发现可自动遍历,因为每次刷新页面,vue实例创建都需要进行create()生命周期,所有他都会发送请求,去给后端获取到数据,从而遍历数据,在前端页面上。
10、用户添加功能
- 给【提交按钮】,绑定单击事件
- 给表单的对应值,进行双向绑定
- 编写saveUserInfo()函数
data: {
users:[], //users数据赋值来源于后端服务接口,在页面加载完成之前完成赋值
saveUser:{
}, //用来完成数据双向绑定
},
methods: {
//保存用户信息的函数
saveUserInfo(){
console.log(this.saveUser);
axios.post("http://localhost:6161/users/user/save",this.saveUser)
.then(function (resp) {
console.log(resp.data);
}).catch(function (err) {
console.log(err);
})
},
},
saveUser这个变量给保存上面填入的表单数据,在给下面saveUserInfo函数来获取对应的表单数据,再发送post请求给后端保存对应的表单数据
接下来给后端添加save保存用户的方法
- UserDao
//保存用户
void save(User user);
- UserDao.xml
<!--保存用户-->
<insert id="save" parameterType="User">
insert into t_user VALUES(#{id},#{name},#{age},#{salary},#{phoneNumber})
</insert>
- UserService接口
//保存用户
public void save(User user);
- UserServiceImpl
@Override
public void save(User user) {
user.setId(UUID.randomUUID().toString());
userDao.save(user);
}
- UserController
因为每个方法都会跨域访问,使用在类上直接标注@CrossOrigin
告诉spring,这个类下的所有方法都需要解决跨域问题
@RestController
@RequestMapping("/user")
@CrossOrigin //允许可以跨域操作,解决Vue静态页面访问的跨域问题
public class UserController {
@Autowired
private UserService userService;
//保存用户
@PostMapping("/save")
public Map<String,Object> save(@RequestBody User user){
Map<String,Object> map = new HashMap<>();
try {
userService.save(user);
map.put("success",true);
map.put("msg","用户保存【成功】");
} catch (Exception e) {
e.printStackTrace();
map.put("fail",false);
map.put("msg","用户保存【失败】");
}
return map;
}
}
- 测试
保存成功,测试通过
- 发现用户数据保存成功后应该要重新刷新一下表单的数据,所以就重新调用一下查询所有用户信息
保证代码不冗余,把created()中的方法提取出来,定义成findAll()函数
- 最后保存用户信息完成后,要清空上一次保存用户的信息
11、重置按钮功能
- 给【重置按钮】板顶单击事件
- 定义reset事件函数,因为数据的双向绑定。
//重置表单数据
reset(){
this.saveUser = {
};
}
12、删除功能实现
- 给【删除按钮】绑定单击事件,事件根据传入的id删除对应的数据
- UserDao
//根据id删除用户
void deleteById(String id);
- UserDao.xml
<!--根据id删除用户-->
<delete id="deleteById" parameterType="String">
delete from t_user where id = #{id}
</delete>
- UserService
//根据id删除用户
public void deleteById(String id);
- UserServiceImpl
@Override
public void deleteById(String id) {
userDao.deleteById(id);
}
- UserController
//根据用户id删除信息
@GetMapping("/deleteById")
public Map<String,Object> deleteById(@RequestBody String id){
Map<String,Object> map = new HashMap<>();
try {
userService.deleteById(id);
map.put("success",true);
map.put("msg","用户删除【成功】");
} catch (Exception e) {
e.printStackTrace();
map.put("fail",false);
map.put("msg","用户删除【失败】");
}
return map;
}
- 前端vue
//删除用户信息
deleteUserInfo(id){
if (window.confirm("是否确定要删除这条记录吗???")){
//使用axios发送请求根据id删除用户信息
console.log(id);
let _this = this;
axios.get("http://localhost:6161/users/user/deleteById?id="+id)
.then(function (resp) {
console.log(resp);
if (resp.data.success){
//更新页面数据
_this.findAll();
}else {
alert(resp.data.msg);
}
}).catch(function (err) {
console.log(err);
});
}
}
13、修改功能
- 给【修改按钮】绑定事件
- UserDao接口
//根据id查询一个人信息
User findOne(String id);
- UserDao.xml
<!--根据id查询一个用户信息-->
<select id="findOne" resultType="User" parameterType="String">
select id,name,age,salary,phoneNumber from t_user where id = #{id}
</select>
- UserServiceImpl
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public User findOne(String id) {
return userDao.findOne(id);
}
- UserController
//根据用户id查询该用户信息
@GetMapping("findOne")
public User findOne(String id){
return userService.findOne(id);
}
- 前端vue,findOneUserInfo()函数
//查询一个人的信息
findOneUserInfo(id){
let _this =this;
//根据id查询一个人的信息
axios.get("http://localhost:6161/users/user/findOne?id="+id)
.then(function (resp) {
console.log(resp.data);
//通过数据的双向绑定,直接赋值,就可以显示了
_this.saveUser=resp.data;
}).catch(function (err) {
console.log(err);
})
}
- 测试
上面通过将数据回显在右侧表单中,因为阿昌这里的保存用户信息和修改用户信息都用的右侧表单,所以需要进行再修改
- UserDao接口
//根据id修改用户信息
void update(User user);
- UserDao.xml
<!--根据id修改用户信息-->
<update id="update" parameterType="User">
update t_user set name=#{name},age=#{age},salary=#{salary},phoneNumber=#{phoneNumber}
where id = #{id}
</update>
- UserService
//根据id修改用户信息
public void update(User user);
- UserServiceImpl
@Override
public void update(User user) {
userDao.update(user);
}
- 修改之前的保存用户方法,将其合成一个修改、保存方法
//保存用户
@PostMapping("/save")
public Map<String,Object> save(@RequestBody User user){
Map<String,Object> map = new HashMap<>();
try {
//判断传来的user对象是否有id值,有为保存操作,没有为修改操作
if (StringUtils.isEmpty(user.getId())){
userService.save(user);
}else {
userService.update(user);
}
map.put("success", true);
} catch (Exception e) {
e.printStackTrace();
map.put("fail",false);
map.put("msg","用户保存或更新失败");
}
return map;
}
- 测试【修改功能是否实现】
查看数据库是否修改成功:↓↓↓
- 测试【保存功能】是否可用
14、搜索功能实现
- UserDao接口
//根据姓名或者电话进行模糊搜索
//@Param:参数绑定
List<User> findNameOrPhoneNumber(@Param("name") String name, @Param("num") String phoneNumber);
- UserDao.xml
<!--处理模糊检索
动态sql,根据是否有name,num来动态的检索
通过#{},获取的数据如果在方法中有使用@Param注解的话,就要使用@Param注解的数据绑定名称
-->
<select id="findNameOrPhoneNumber" resultType="User">
select id,name,age,salary,phoneNumber from t_user
<where>
<if test="name!=''">
name like concat(#{name},'%')
</if>
<if test="num!=''">
OR phoneNumber like concat('%',#{num},'%')
</if>
</where>
</select>
- UserService接口
//模糊检索
public List<User> findNameOrPhoneNumber(String name,String num);
- UserServiceImpl
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public List<User> findNameOrPhoneNumber(String name, String num) {
return userDao.findNameOrPhoneNumber(name, num);
}
- UserController
//模糊检索
@GetMapping("/findNameOrNum")
public List<User> findNameOrNum(String name,String num){
return userService.findNameOrPhoneNumber(name,num);
}
- vue前端
给【搜索按钮】绑定单击事件,并通过.prevent
阻止默认行为
为其进行数据绑定
//模糊检索
searchLike(){
let _this = this
console.log(this.searchName);
console.log(this.searchNum);
axios.get("http://localhost:6161/users/user/findNameOrNum?name="+_this.searchName+"&num="+this.searchNum)
.then(function (resp) {
console.log(resp.data);
_this.users = resp.data;
})
},
- 测试
- 主页面展示