vue进阶篇— 适用于后端开发人员的Vue axios 组件化开发教程_vue结合springboot开发

此文为vue进阶篇,包含vue路由、组件、axios请求以及结合springboot开发实例
入门篇链接地址https://blog.csdn.net/qq_41157588/article/details/115085686
代码完整无水分,供学习参考,更多了解信息请看文末.
总结不易 点赞评论 支持 thank ~

10.Axios基本使用

10.1Axios引言

Axios是一个异步请求技术,核心作用就是用来在页面中发送异步请求,

并获取对应数据在在页面中渲染 页面局部更新技术 Ajax

Axios中文网 http://www.axios-js.com/zh-cn/docs/

10.2Axios安装方式

  1. 使用 npm
$ npm install axios
  1. 使用 bower
$ bower install axios
  1. 使用 cdn(注:需要联网)
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

10.3GET方式请求

Axios使用准备工作=> 在Axios进行 Get和Post请求时,此处请求的地址和数据是结合springboot接口进行模拟的,请按照以下图及代码使用IDEA创建一个springboot项目,用前端vue Axios进行GET和POST请求的使用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sdEKJyeG-1616410878478)(D:/typora/Typora/img/vue/1616395721992.png)]

User实体代码

@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@ToString
public class User {
    private Integer id;
    private String username;
    private String email;
    private Integer age;
    private String phone;
}

UserController代码

@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> delete(@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 id){
        System.out.println("id = " + id);

        List<User> users = new ArrayList<>();
        users.add(new User(1,"axios测试值1","ti66666@vip.qq.com",21,"15155556666"));
        users.add(new User(2,"axios测试值2","ti66666@vip.qq.com",22,"15656667777"));
        users.add(new User(3,"axios测试值3","ti66666@vip.qq.com",23,"17666663959"));
        return users;
    }
}

数据准备完成。接下来准备上手axios的get和post请求,测试请求要注意和后端服务端口对应

Axios GET请求Vue代码

<!-- 引入Axios -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>axios的GET方式请求使用</title>
	</head>
	<body>
		<!-- 引入Axios -->
		<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
		
		<!-- 发送GET方式的请求 -->
		<script>
			axios.get("http://localhost:8989/user/findAll?id=1").then(function(response){
				console.log(response.data);
			}).catch(function(err){
				console.log(err);
			})
		</script>			
	</body>
</html>

10.4POST方式请求

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>axios的POST方式请求使用</title>
	</head>
	<body>
		<!-- 引入在线Axios -->
		<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
		
		<script>
			axios.post("http://localhost:8989/user/save",{
				id:5,
				username:"xiangti",
				age:22,
				email:"ti66666@vip.qq.com",
				phone:13215882222
			}).then(function(response){
				console.log(response);
			}).catch(function(err){
				console.log(err);
			})
		</script>
	</body>
</html>

10.5axios并发请求

并发请求:将多个请求在同一时刻发送后到后端服务接口,最后在集中处理每个请求的响应结果

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>axios并发请求</title>
	</head>
	<body>
		<!-- 引入在线Axios -->
		<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
		
		<script>
			// 1.创建一个查询所有的请求
			function findAll(){
				return axios.get("http://localhost:8989/user/findAll?id=1")
			}
			// 2.创建一个保存的请求
			function save(){
				axios.post("http://localhost:8989/user/save",{
					id:5,
					username:"xiangti",
					age:22,
					email:"ti66666@vip.qq.com",
					phone:13215882222
				})
			}
			// 3.并发执行
			// axios.all(findAll(),save());
			
			axios.all([findAll(),save()]).then(
				axios.spread(function(res1,res2){
					console.log(res1.data);
					console.log(res2.data);
				})
			)//用来发送一组并发请求

		</script>		
	</body>
</html>

此时在IDEA和网页的NetWork看到执行了两条请求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uM7GwNrX-1616410878487)(D:/typora/Typora/img/vue/1616397186209.png)]
在这里插入图片描述

vue结合axios天气查询案例

后端数据模拟api

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gox97KhR-1616410878506)(D:/typora/Typora/img/vue/1616402452935.png)]

上图WeatherController代码 (注意:前端请求端口要和后端的端口对应)

@RestController
@RequestMapping("city")
public class WeatherController {
    @GetMapping("/find")
    @CrossOrigin//跨域注解
    //http://localhost:8989/city/find?name=江苏
    public Map<String,String> findWeatherByCity(String name){
        Map<String, String> map = new HashMap<>();
        String weathers = getWeathers(name);
        // map.put(name,weathers);
        map.put("CityWeatherMsg",weathers);
        return map;
    }

    //返回对应城市的天气情况
    public String getWeathers(String name) {
        Map<String,String> weathers = new HashMap<>();
        weathers.put("河南","晴天 23℃-27℃,天气情况良好");
        weathers.put("江苏","多云转阴 20℃-26℃,天气挺好");
        weathers.put("北京","大雨 14℃-19℃,天气很不好");
        weathers.put("上海","多云 27℃-31℃,天气可以");
        return weathers.get(name);
    }
}

前端代码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>vue结合axios天气查询案例</title>
	</head>
	<body>
		<div id="app">
			<!-- 双向绑定城市信息,点删除键时 隐藏天气信息,回车时,直接搜索 -->
			<input type="text" v-model="cityname" @keyup.delete="shows" @keyup.enter="searchCity" placeholder="请输入如下的城市"/>
			<input type="button" value="搜索" @click="searchCity"/><br>
			<span v-for="city in hotCitys">
				<!-- prevent阻止a标签的默认行为 -->
				<a href="javascript:;" @click.prevent="searchCitys(city)">{{ city }}</a> &nbsp;
			</span>
			<span style="color: red;"> <=仅支持提供的城市数据查询</span>
			<hr >
			<span v-show="isShow">城市: {{cityname}}  -> 获取后台的天气数据: {{msg}}</span>
		</div>

		<!-- 引入在线cdn的vue.js地址-->
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
		<!-- 引入在线cdn Axios -->
		<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

		<script>
			const app = new Vue({
				el: "#app", //element:用来指定vue作用范围
				data: { //data:用来定义vue实例相关数据
					hotCitys: ["河南", "江苏", "北京", "上海"],
					cityname:"",
					msg:"",
					isShow:false
				},
				methods: { //methods:用来定义vue事件处理函数
					searchCity(){
						// 获取输入的城市信息
						console.log("外this作用域信息"+this+"** | **"+"当前输入城市信息:"+this.cityname);
						let _this = this;
						//发送axios请求
						axios.get("http://localhost:8989/city/find?name="+this.cityname).then(function(response){
							console.log("内this作用域信息"+this+"** | **"+"后台响应CityWeather信息:"+response.data.CityWeatherMsg);
							//把获取到的后台map的CityWeatherMsg键值赋值给页面上的msg
							_this.msg = response.data.CityWeatherMsg;
							_this.isShow = true;
							console.log("------------------------");
						}).catch(function(err){
							console.log(err);
						})
					},
					searchCitys(name){
						//把name传入到a标签中的city值,再调取cityname进行赋值
						this.cityname = name;
						//函数中再次调函数 
						this.searchCity();
					},
					shows(){
						this.isShow = false;
					}
				}
			})
		</script>
	</body>
</html>

11.Vue生命周期

生命周期钩子 => 生命周期函数

在这里插入图片描述

12.vue结合前端springboot前后端分离开发综合案例crud

项目结构图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Rh4Gz061-1616588100501)(D:/typora/Typora/img/vue/2021-03-24_195954.png)]

最终效果图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W4bBLAXE-1616588100511)(D:/typora/Typora/img/vue/1616587360010.png)]

sql

自行添加更多的数据

/*
SQLyog Ultimate v12.3.1 (64 bit)
MySQL - 5.7.20-log : Database - stu_newest
*********************************************************************
*/


/*!40101 SET NAMES utf8 */;

/*!40101 SET SQL_MODE=''*/;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`stu_newest` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `你的数据库`;

/*Table structure for table `v_user` */

DROP TABLE IF EXISTS `v_user`;

CREATE TABLE `v_user` (
  `id` int(10) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `name` varchar(40) DEFAULT NULL COMMENT '名字',
  `age` int(3) DEFAULT NULL COMMENT '年龄',
  `salary` double(7,2) DEFAULT NULL COMMENT '薪资',
  `phoneCode` varchar(11) DEFAULT NULL COMMENT '电话',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;

/*Data for the table `v_user` */

insert  into `v_user`(`id`,`name`,`age`,`salary`,`phoneCode`) values 

(1,'admin',15,50000.00,'15545853564'),

(2,'xiangti',21,99999.00,'15368485275'),

(3,'tizi',20,10000.00,'17666663959'),

(4,'小花',19,17000.00,'18588745952'),

(5,'阿名',23,19000.00,'16859267368'),

(6,'girl',20,20000.00,'16815964211'),

(7,'boy',24,2603.00,'13842156415'),

(8,'华哥',20,15151.00,'16484232515');

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

application.yml 配置

server:
  port: 8989 #端口号8989
  servlet:
    context-path: /user #默认访问路径/user

spring:
  application:
    name: vue-crud
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/stu_newest?characterEncoding=utf-8
    username: root
    password: 12345678


mybatis:
  mapper-locations: classpath:/mybatis/mapper/*.xml
  type-aliases-package: com.lemon.bean

User 实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Accessors(chain = true)//开启链式写法
public class User {
    private Integer id;
    private String name;
    private Integer age;
    private Double salary;
    private String phoneCode;
}

UserMapper 数据访问接口

@Mapper
public interface UserMapper {
    //查询所有信息
    List<User> findAll();
    //添加用户
    void save(User user);
    //删除用户
    void del(int id);

    //根据id查当前信息
    User findOne(Integer id);
    //根据id修改信息
    void update(User user);

    //根据姓名或电话模糊搜索
    List<User> findNameOrPhoneCode(@Param("name") String name,@Param("phoneCode") String phoneCode);
}

PageMapper 分页数据访问接口

@Mapper
public interface PageMapper<T, K> {
    /**
     *
     * @param start 当前页
     * @param rows 页大小
     * @return
     */

    public List<T> findByPage(@Param("start") Integer start, @Param("rows") Integer rows);

    /**
     * 总条数
     * @return
     */
    public Integer findTotals();
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace=绑定一个指定的dao/mapper接口-->
<mapper namespace="com.lemon.mapper.UserMapper">

    <!--处理模糊搜索-->
    <select id="findNameOrPhoneCode" resultType="user">
        select id,name,age,salary,phoneCode from v_user
        <where>
            <if test="name != ''">
                name like concat(#{name},'%')
            </if>

            <if test="phoneCode != ''">
                or phoneCode like concat('%',#{phoneCode},'%')
            </if>
        </where>
    </select>

    <!--根据id修改当前信息-->
    <update id="update" parameterType="user">
        update v_user set name=#{name},age=#{age},salary=#{salary},phoneCode=#{phoneCode} where id = #{id}
    </update>
    <!--根据id查询当前信息-->
    <select id="findOne" resultType="user" >
        select id,name,age,salary,phoneCode from v_user where id = #{id}
    </select>
    <!--根据id删除一条信息-->
    <delete id="del" parameterType="Integer">
        delete from v_user where id = #{id}
    </delete>

    <!--开启自增 id,不设置也可以,数据库已经设置自增-->
    <!--<insert id="save" parameterType="user" useGeneratedKeys="true" keyProperty="id">-->
    <insert id="save" parameterType="user">
        insert into v_user values (#{id},#{name},#{age},#{salary},#{phoneCode})
    </insert>

    <!--查询所有数据-->
    <select id="findAll" resultType="user">
        select id,name,age,salary,phoneCode from v_user
    </select>
</mapper>

PageMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace=绑定一个指定的dao/mapper接口-->
<mapper namespace="com.lemon.mapper.PageMapper">
    <!--分页查询所有-->
    <select id="findByPage" resultType="user">
        select id,
        name,
        age,
        salary,
        phoneCode
        from v_user
        order by id ASC
        limit #{start},#{rows}
    </select>

    <!--查询总条数-->
    <select id="findTotals" resultType="integer">
        select count(id) from v_user
    </select>
</mapper>

UserService

public interface UserService {
    //查询所有信息
    List<User> findAll();
    //添加用户
    void save(User user);
    //删除用户
    void del(int id);

    //根据id查当前信息
    User findOne(Integer id);
    //根据id修改信息
    void update(User user);

    //根据姓名或电话模糊搜索
    List<User> findNameOrPhoneCode(@Param("name") String name, @Param("phoneCode") String phoneCode);
}

UserServiceImpl

@Service
public class UserServiceImpl implements UserService{

    @Resource
    private UserMapper userMapper;

    @Override
    public List<User> findAll() {
        return userMapper.findAll();
    }

    @Override
    public void save(User user) {
        userMapper.save(user);
    }

    @Override
    public void del(int id) {
        userMapper.del(id);
    }

    @Override
    public User findOne(Integer id) {
        return userMapper.findOne(id);
    }

    @Override
    public void update(User user) {
        userMapper.update(user);
    }

    @Override
    public List<User> findNameOrPhoneCode(String name, String phoneCode) {
        return userMapper.findNameOrPhoneCode(name,phoneCode);
    }
}

PageService

public interface PageService {
    /**
     * @param page  当前页
     * @param rows  每页显示的记录数
     * @return
     */
    public List<User> findByPage(Integer page,Integer rows);

    /**
     * 查询总条数
     * @return
     */
    public Integer findTotals();
}

PageServiceImpl

@Service
public class PageServiceImpl implements PageService {

    @Resource
    private PageMapper pageMapper;

    @Override
    public List<User> findByPage(Integer page, Integer rows) {
        //页码计算公式 (当前页-1) * 页大小
        int start = (page - 1) * rows;
        return pageMapper.findByPage(start, rows);
    }

    @Override
    public Integer findTotals() {
        return pageMapper.findTotals();
    }
}

UserController

@Controller
@RestController
@CrossOrigin//允许跨域处理
public class UserController {
    @Resource
    private UserService userService;

    //模糊搜索
    @GetMapping("/findLike")
    public List<User> findNameOrPhoneCode(String name,String code){
        System.out.println("前端模糊搜索  name值:"+name+"  |  phone值: " +code);
        return userService.findNameOrPhoneCode(name,code);
    }

    @GetMapping(value = "/findOne")
    //根据id查询当前信息
    public User findOne(int id){
        System.out.println("前端查询当前信息id:" +id);
        return userService.findOne(id);
    }

    @PostMapping(value = "/del")
    //删除用户
    public Map<String,Object> del(int id){
        System.out.println("前端删除id值:"+id);
        Map<String, Object> map = new HashMap<>();
        try {
            //前端传的值为string类型,定义的值为integer,强制string类型转integer
            // Integer num = Integer.parseInt(id);
            userService.del(id);
            map.put("state",true);
        } catch (Exception e) {
            map.put("state",false);
        }
        return map;
    }

    @PostMapping(value = "/save")
    //保存用户_修改用户
    public Map<String, Object> save(@RequestBody User user) {
        System.out.println("前端save信息(有id修改 无id添加): " + user);
        Map<String, Object> map = new HashMap<>();
        if (!user.equals("") && user!=null) {
            //如果没有id执行的是添加操作
            if (StringUtils.isEmpty(user.getId())){
                userService.save(user);
                map.put("state", true);
                map.put("msg","添加成功");
            }else{
                //如果有id执行的是修改操作
                userService.update(user);
                map.put("state", true);
                map.put("msg","修改成功");
            }
        } else {
            map.put("state", false);
            map.put("msg", "保存或修改失败");
        }
        return map;
    }

    //查询所有信息(已无作用,后期加了分页查询数据)
    @GetMapping("/findAll")
    public List<User> findAll() {
        List<User> userList = userService.findAll();
        return userList;
    }
}

PageController

@Controller
@CrossOrigin//允许跨域处理
public class PageController {
    @Resource
    private PageService pageService;

    @GetMapping("/findByPage")
    @ResponseBody
    public Map<String,Object> findByPage(Integer page,Integer rows){
        System.out.println("前端页码:"+ page);

        //page=null 页面为1
        page = page==null?1:page;
        //rows=null 每页展示五条数据
        rows = rows==null?5:rows;

        HashMap<String, Object> map = new HashMap<>();
        //分页处理
        List<User> userList = pageService.findByPage(page, rows);
        //计算总页数
        Integer totals = pageService.findTotals();
        //总页数  count%rows==0 如果等于0执行 count/rows  否则执行count/rows+1
        Integer totalPage = totals%rows==0?totals/rows:totals/rows+1;
        if(page>totalPage){
            map.put("state",true);
            map.put("msg","已经是最后一页了 没有更多的数据啦~");
        }

        map.put("userList",userList);//放入用户id集合
        map.put("totals",totals);//放入总条数的方法
        map.put("totalPage",totalPage);//放入总页数
        map.put("page",page);//放入当前页
        return map;
    }
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>User Manager</title>
    <!--引入bootstrap中css的样式-->
    <link rel="stylesheet" href="../static/css/bootstrap.min.css">
    <style type="text/css">
        tr th {
            text-align: center;
        }

        td {
            text-align: center;
        }

    </style>
</head>
<body>

<!--导航-->
<nav class="navbar navbar-default">
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
            <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="#">x</a></li>
            </ul>
        </div>
    </div>
</nav>

<div id="app">
    <!--中心布局-->
    <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="exampleInputName2">姓名</label>
                        <input type="text" placeholder="输入搜索姓名的关键字" v-model="searchName" class="form-control"
                               id="searchName">
                    </div>
                    <div class="form-group">
                        <label for="exampleInputEmail2">电话</label>
                        <input type="email" placeholder="输入电话的关建数" v-model="searchPhone" class="form-control"
                               id="searchEmail">
                    </div>
                    <button type="submit" class="btn btn-info" @click.prevent="searchLike">搜索</button>
                </form>
            </div>
        </div>

        <div class="row">
            <div class="col-md-8" style="margin-top: 50px">
                <table class="table table-striped table-bordered table-hover">
                    <thead>
                    <tr>
                        <th>ID</th>
                        <th>姓名</th>
                        <th>年龄</th>
                        <th>薪资</th>
                        <th>电话</th>
                        <th>操作</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr v-for="user,index in users" :key="user.id">
                        <td>{{user.id}}</td>
                        <td>{{user.name}}</td>
                        <td>{{user.age}}</td>
                        <td>{{user.salary}}</td>
                        <td>{{user.phoneCode}}</td>
                        <td>
                            <button class="btn btn-danger" @click="delRow(user.id)">删除</button>&nbsp;
                            <button class="btn btn-primary" @click="findOneUserInfo(user.id)">修改</button>
                        </td>
                    </tr>
                    </tbody>
                </table>
            </div>

            <div class="col-md-4">
                <div class="form-group" style="margin: 0px" align="center">
                    <span><h3>添加 | 修改 模块</h3></span><br>
                    <span>表单默认为添加数据不携带id / 点修改自动获取id 携带id进行修改</span>
                </div>
                <span></span>
                <form>
                    <div class="form-group">
                        <label for="username">姓名</label>
                        <input type="text" class="form-control" required id="username" v-model="userparameter.name"
                               placeholder="请输入姓名">
                    </div>
                    <div class="form-group">
                        <label for="password">年龄</label>
                        <input type="text" class="form-control" id="password" v-model="userparameter.age"
                               placeholder="请输入年龄">
                    </div>
                    <div class="form-group">
                        <label for="salary">薪资</label>
                        <input type="text" class="form-control" id="salary" v-model="userparameter.salary"
                               placeholder="请输入薪资">
                    </div>
                    <div class="form-group">
                        <label for="phoneCode">电话</label>
                        <input type="text" class="form-control" id="phoneCode" v-model="userparameter.phoneCode"
                               placeholder="请输入电话号码">
                    </div>

                    <button type="submit" class="btn btn-warning" @click="saveUserInfo">提交</button>
                    <button type="reset" class="btn btn-info">重置</button>
                </form>
            </div>
        </div>
    </div>

    <!--分页 未添加样式版-->
    <div id="pages" style="margin-left: 270px;">
        <!--此处注释掉的代码为控制首页 和 尾页的 上一页和下一页标签隐藏-->
        <!--<a href="javascript:;" class="page" v-if="page!=1" disabled @click="pagePart(page-1)">&lt;上一页</a>-->
        <a href="javascript:;" class="page"  disabled @click="pagePart(page-1)">&lt;上一页</a>
        &nbsp;&nbsp;
        <a href="javascript:;" class="page" v-for="indexpage in totalPage" @click="pagePart(indexpage)">&nbsp;&nbsp;{{indexpage}}&nbsp;&nbsp;</a>
        <!--<a href="javascript:;" class="page" v-if="page<totalPage" @click="pagePart(page+1)">下一页&&gt;</a>-->
        <a href="javascript:;" class="page"  @click="pagePart(page+1)">下一页&gt;</a>
    </div>


</div>

<!--引入Vue.js-->
<script src="../static/js/vue.js"></script>
<!--引入axios.js-->
<script src="../static/js/axios.min.js"></script>
<script>
    const app = new Vue({
        el: "#app",
        data: {
            users: [],//数据赋值来源于后端服务接口,在页面加载完成前完成赋值
            userparameter: {},//定义添加数据的双向绑定,此处如为[]会报错
            searchName: "",//处理搜索名字的数据绑定
            searchPhone: "",//处理搜索电话的数据绑定

            page: 1,//当前页 默认1
            rows: 5,//行数 默认5
            totalPage: 0,
            totals: 0,
        },
        methods: {
            //查询所有数据 并进行分页
            pagePart(indexpage) {//查询所有
                if (indexpage) {
                    this.page = indexpage;
                }
                axios.get("http://localhost:8989/user/findByPage?page=" + this.page).then((res) => {
                    // console.log(res.data.userList);
                    if (res.data.state) {
                        //当处于最后一页时,再点击下一页响应后台msg信息
                        alert(res.data.msg);
                        //刷新页面
                        location.reload();
                    }
                    this.users = res.data.userList;
                    this.page = res.data.page;
                    this.totalPage = res.data.totalPage;
                    this.totals = res.data.totals;
                });
            },
            searchLike() {
                //模糊搜索
                axios.get("http://localhost:8989/user/findLike?name=" + this.searchName + "&code=" + this.searchPhone).then((res) => {
                    console.log(res.data);
                    this.users = res.data;
                })
            },
            //根据id查询当前的信息(修改)
            findOneUserInfo(id) {
                axios.get("http://localhost:8989/user/findOne?id=" + id).then((res) => {
                    console.log(res.data);
                    //根据双向绑定原理,后台直接赋值给userparameter
                    this.userparameter = res.data;
                });
            },
            //根据id删除信息
            delRow(id) {
                if (confirm("确认删除id为 " + id + "信息吗")) {
                    axios.post("http://localhost:8989/user/del?id=" + id).then((res) => {
                        if (res.data.state) {
                            alert("删除id " + id + " 信息成功");
                            location.reload(); //刷新当前页
                        } else {
                            alert("删除失败");
                        }
                    });
                }
            },
            //添加信息
            saveUserInfo() {
                axios.post("http://localhost:8989/user/save", this.userparameter).then((res) => {
                    if (res.data.state) {
                        alert(res.data.state + " " + res.data.msg);
                        //添加完成后刷新当前页 location.reload()或调取 this.findAll
                        location.reload();
                        //清空文本框的信息
                        this.userparameter = "";
                    } else {
                        alert("后台:" + res.data.state + " " + res.data.msg);
                    }
                }).catch((err) => {
                    alert("添加失败 错误信息: " + err);
                });
            },
            //查询所有用户信息的函数 (后期已加入分页查数据,当前无用)
            // findAll() {
            //     //已简写为以下的箭头函数
            //     axios.get("http://localhost:8989/user/findAll").then((res) => {
            //         // console.log(res.data);
            //         this.users = res.data;
            //     }).catch((err) => {
            //         console.log("查询所有错误信息:" + err);
            //     })
            // },
        },
        //生命周期相关函数 页面加载直接调用
        created() {
            //调用查询所有信息函数
            // this.findAll();
            this.pagePart();
        }
    })
</script>
</body>
</html>

static静态文件说明

在这里插入图片描述

static静态文件为 bootstrap vue.js vue.min.axios 此处没有放入这些文件,可以尝试在inedx.html删除现有的link和script 导入如下cdn

<!--引入bootstrap-->
<link href="https://cdn.bootcdn.net/ajax/libs/twitterbootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">

<!--引入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

<!--引入axios.js-->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

test测试类

@SpringBootTest
class VueTest {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private PageService pageService;
    
    @Test
    void findAll() {
        userMapper.findAll().forEach(user -> System.out.println("user = " + user));
    }

    //分页测试
    @Test
    public void testFindByPage() {
        List<User> list = pageService.findByPage(1, 3);
        //jdk8的新特性
        list.forEach(province -> {
            System.out.println(province);
        });
    }

}

13.Vue组件

13.1组件作用

组件作用:用来减少vue实例对象中代码量,之后在使用vue开发的过程中,可根据不用业务功能划分不同的多个组件,然后由多个组件去完成整个页面的布局,便于以后使用vue开发时页面管理,方便开发人员维护

13.2组件使用

13.2.1全局组件的注册

全局组件注册给vue实例,以后可以在任何vue实例范围内使用该组件

开发全局组件

<!--使用全局组件-->
<login></login>

//全局组件注册 (参数1:组件名称 参数2:组件配置对象 template:用来书写组件html代码 注意在template中必须存在一个容器 )
Vue.component('login', {
    template: '<div><h1>用户登录</h1></div>'
})

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LXCROhpt-1616920135864)(D:/typora/Typora/img/vue/1616634833721.png)]

# 注意:
	1. Vue.component用来开发全局组件 参数1:组件的名称  参数2:组件配置{}  template:‘ ’ 用来书写组件的html代码  template中必须只有有 且只有一个root元素
	2.使用时需要在Vue的作用范围内根据组件名使用 Vue 全局组件
	3.如在注册组件时使用驼峰式命名时,注意在调用时用 - 来衔接,全部小写,如下示例
    <user-login></user-login>
    
    Vue.component('userLogin', {
        template: '<div><h1>用户登录</h1></div>'
    })
13.2. 局部组件的注册

通过将组件注册给对应Vue实例中一个components属性来完成组件注册,这种方式不会对Vue实例造成累加

局部组件注册推荐使用第二种

第一种开发方式

<div id="app">
    <login></login>
</div>
<!-- 引入在线cdn的vue.js地址-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<script>
    //局部组件登录模板 1 x
    const app = new Vue({
        el: "#app",
        data: {},
        methods: {},
        components: { //用来注册局部组件
            login: {//局部组件名称
                template: '<div><h2>用户管理</h2></div>'
            }
        }
    })
</script>
-----------------------------------------------------------------------
<script>
    //局部组件登录模板  2 *
    let login = {//具体局部组件名称
        template: '<div><h2>用户管理</h2></div>' }
    const app = new Vue({
        el: "#app",
        data: {},
        methods: {},
        components: { //用来注册局部组件
            login:login //注册局部组件
        }
    })
</script>

第二种开发方式

<div id="app">
    <!--4.局部组件使用 在vue实例范围内-->
    <login></login>
    <login></login>
</div>

<!-- 1.引入在线cdn的vue.js地址-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<!--2.生命局部变量模板 template 标签,注意:在vue实例作用外声明-->
<template id="loginTemplate"><h2>用户登录</h2></template>

<!--3.注册组件-->
<script>
    let login = {//具体局部组件名称
        template:'#loginTemplate'
    }
    const app = new Vue({
        el: "#app",
        data: {},
        methods: {},
        components: { //用来注册局部组件
            //login: login //注册局部组件 
            login  //:后内容可直接去掉调用
        }
    })
</script>

13.3 Prop的使用

官网示例

prop用来给组件传递相应静态数据或动态数据

13.3.1通过在组件上声明静态数据传递给组件内部
//1.声明组件模板对象
let login = {
    template: "<div><h1>欢迎:{{userName}}  age:{{age}}</h1></div>",
    props:['userName','age'] //props 用来接收使用组件时通过组件中标签传递的数据
}
//2.注册组件
const app = new Vue({
    el: "#app",
    data: {},
    methods: {},
    components: {
        login //组件注册
    }
})
//3.通过组件完成数据传递
<login user-name="柠檬" age="21"></login>
# 总结
	1.使用组件时可以再组件上定义多个属性以及对应数据
	2.在组件内部可以使用props数组声明多个定义在组件上的属性名,之后可以在组件中通过{{属性名}}方式获取组件中属性值
13.3.2通过组件声明动态数据传递给组件内部
//1.声明组件模板对象
let comp = {
    template: '<div><h2>欢迎:{{name}}</h2> 年龄:{{age}}</div>',
    props:['name','age']
}
    
//2.注册局部组件
const app = new Vue({
    el: "#app",
    data: {
        username:"提先森",
        age:21
    },
    methods: {},
    components: {
        login:comp, //注册组件
    }
})

//3.使用组件
<login :name="username" :age="age"></login>

使用v-bind形式将数据绑定在vue实例中data属性,之后data属性发生变化,组件内部数据跟着变化
13.3.3单向数据流

所有的 prop 都使得其父子 prop 之间形成了一个 单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行

所有 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。

额外的,每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。 ------摘自官网

13.4组件中定义数据和事件

1.组件中定义属于组件的数据

<div id="app">
    <!--组件的使用-->
    <login></login>
</div>

//组件声明的配置对象
    let comp = {
        template: '<div>' +
            '<h2>平淡安好</h2>' +
            '<span>{{msg}}</span>' +
            '<ul><li v-for="list,index in lists">{{index+1}}  {{list}}</li></ul>'+
            '</div>',
        data() { //组件中自己的数据 使用data函数定义组件的属性  在template代码中通过插值表达式获取值
            return {
                msg: "template data",
                lists:["java","php","python"]
            }
        }
    }  
	const app = new Vue({
        el: "#app",
        data: {},
        methods: {},
        components: {
            login: comp //注册组件
        }
    })

2.组件中事件定义

<div id="app">
    <login></login>
</div>

<!-- 引入在线cdn的vue.js地址-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    let comp = {
        template: '<div><input type="button" value="点击" @click="change""></div>',
        data() {
            return {
                name:"提先森"
            }
        },
        methods: {
            change() {
                alert(this.name);
            }
        }
    }
    const app = new Vue({
        el: "#app",
        components: {
            login: comp
        }
    })
# 总结
	1.组件中定义事件和直接在vue中定义事件基本一致,直接在组件内部对应的html代码加入@事件=函数名方式即可
	2.在组件内部使用methods属性用来定义对应的事件函数即可,事件函数中this指向的是当前组件的实例

13.5向vue子组件中传递事件并在子组件中调用该事件

在子组件中调用传递过来的相关事件必须使用this.$emit(“函数名”) 方式调用

//1.声明组件
    const login = {
        template:'<div><h2>平淡安好</h2><input type="button" @click="change" value="点击"><br>{{uname}}</div>',
        data(){
            return{
                uname:this.name,
            }
        },
        methods:{
            change(){
                //调用vue实例中的函数
                this.$emit("vc");//调用组件传递来的其他函数时使用 this.$emit('函数名调用')
            }
        },props:['name'],
    }
//2.注册组件
const app = new Vue({
        el: "#app",
        data: {
            username:"提先森",
        },
        methods: {
            vueComp(){ //一个事件函数,将这个vue函数传递给子组件
                alert("vue 实例函数执行");
            }
        },
        components:{
            login //注册组件
        }
    })
//3.使用组件(自己定义名字,绑定父组件事件)
<div id="app">
<login :name="username" @vc="vueComp"></login> //在组件内部使用  this.$emit("vc")调用
</div>

14.vue中路由(VueRouter)

路由官网介绍

14.1路由简介

路由:根据请求的路径按照一定的路由规则进行请求的转发 从而帮助我们实现统一请求的管理

14.2路由做用

用来在vue中实现组件之间的动态切换

vue router官网(包含使用安装_使用路由) https://router.vuejs.org/zh/guide/

14.3使用路由*

1.引入路由

vue.js  cdn
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
vue路由的cdn 在 Vue 后面加载 vue-router,会自动安装的
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

2.创建组件对象

const login = {
    template: '<div><h1>登录</h1></div>'
}
const register = {
    template: '<div><h1>注册</h1></div>'
}

3.定义路由对象规则

//创建路由对象
const router = new VueRouter({
    routes: [
        //path:路由的路径  component:路径对应的组件
        {path: '/login', component: login}, 
        {path: '/register', component: register}
    ]
})

4.将路由对象注册到vue实例

   const app = new Vue({
        el: "#app",
        data: {},
        methods: {},
        router: router //设置路由对象
    })

5.在页面中显示路由组件 根据链接切换路由(注意路径前加 #)

<div id="app">
    <a href="#/login">登录</a>
    <br>
    <a href="#/register">注册</a>
    <!--显示路由的组件-->
    <router-view></router-view>
</div>

完整代码

<div id="app">
    <!--<a href="#/login">点击登录</a>-->
    <!--<a href="#/register">点击注册</a>-->

    <!--router-link好处:书写路由路径不需要 #,  to用来写路由路径-->
    <router-link to="/login" tag="button">点击登录</router-link>
    <router-link to="/register" tag="button">点击注册</router-link>

    <!--显示路由的组件-->
    <router-view></router-view>
</div>

<!-- 引入在线cdn的vue.js地址-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!--引入router.js-->
<script src="./js/vue-router.js"></script>
<script>
    //声明组件模板
    const login = {
        template: '<div><h1>登录</h1></div>'
    }
    const register = {
        template: '<div><h1>注册</h1></div>'
    }
    //创建路由对象
    const router = new VueRouter({
        routes: [
            {path: '/login', component: login},
            {path: '/register', component: register},
        ]
    })

    const app = new Vue({
        el: "#app",
        data: {},
        methods: {},
        router: router //注册路由对象
    })
</script>

14.4 router-link使用

作用:用来替换在切换路由时使用 a 标签切换路由

好处:可以自动给路由路径加入 # ,不需要手动加入

    <!--<a href="#/login">点击登录</a>-->
    <!--<a href="#/register">点击注册</a>-->
    
    <!--router-link好处:书写路由路径不需要 #,  to用来写路由路径 tag渲染指定标签元素-->
    <router-link to="/login" tag="button">点击登录</router-link>
    <router-link to="/register" tag="span">点击注册</router-link>
# 总结
    1.router-link 用来替换使用a标签实现路由切换,好处是不需要书写 # 号,直接写路由路径
    2.router-link to 属性用来书写路由路径   tag属性:用来将router-link渲染成指定的标签

14.5默认路由

作用:用来在第一次进入界面时显示一个默认的组件

  const router = new VueRouter({
      routes: [
          // {path: '/', component: login},
          //默认路由使用的两种形式
          //redirect:当访问的是默认路由 "/" 时,跳转到指定的路由展示 推荐使用此方式
          {path: '/', redirect:'login'},
          
          {path: '/login', component: login},
          {path: '/register', component: register},
      ]
  })

14.6路由中的参数传递

方式一参数传递 传统方式

1.1、通过 ? 号的形式拼接参数

<router-link to="/login?id=21&name=tizi" tag="button">登录</router-link>

1.2.组件中获取参数

 //声明组件模板
 const login = {
     template:'<div><h2>登录</h2></div>',
     data(){return{}},
     methods: {},
     created(){
         console.log("id: " + this.$route.query.id+" name:  "+this.$route.query.name);
     }
 }

方式二参数传递 restful

2.1通过使用路径方式传递

<router-link to="/register/12/tizi" tag="button">注册</router-link>

//创建路由对象
var router = new VueRouter({
   routes:[
       {path:'/register/:id/:name',component:register}, //定义路径获取参数
   ]
});

2.2组件中获取参数

    const register = {
        template:'<div><h2>注册</h2> {{this.$route.params.name}}</div>',
        created() {
            console.log("注册组件id:" +this.$route.params.id+"  注册组件name: "+this.$route.params.id);
        }
    }

14.7嵌套路由

1.声明最外层和内层路由

2.创建路由对象含有嵌套路由 children子路由

3.注册路由对象

4.测试路由

嵌套路由全部代码

<div id="app">
    <router-link to="/product"><span>商品管理</span></router-link>
    <!--显示路由的组件-->
    <router-view></router-view>
</div>

<template id="product">
    <div>
        <h1>商品管理</h1>
        <router-link to="/product/add">商品添加</router-link>
        <router-link to="/product/edit">商品编辑</router-link>
        <!--显示路由的组件-->
        <router-view></router-view>
    </div>
</template>

<!-- 引入在线cdn的vue.js地址-->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!--引入router.js-->
<script src="./js/vue-router.js"></script>
<script>
    //声明组件模板
    const product = {
        template: "#product"
    }
    const add = {
        template: '<div><h1>商品添加</h1></div>'
    }
    const edit = {
        template: '<div><h1>商品编辑</h1></div>'
    }

    //定义路由对象
    var router = new VueRouter({
        routes: [
            {path: "/product", component: product,
                children:[
                    {path: "add", component: add},
                    {path: "edit", component: edit},
                ]
            },
        ]
    })

    const app = new Vue({
        el: "#app",
        data: {},
        methods: {},
        router//注册路由对象
    })
</script>

15. Vue CLI脚手架

Vue-CLI官网

15.1什么是CLI

​ 命令行界面(英语:command-line interface,缩写:CLI)是在图形用户界面得到普及之前使用最为广泛的用户界面,它通常不支持鼠标,用户通过键盘输入指令,计算机接收到指令后,予以执行。

15.2什么是Vue CLI

Vue CLI 是一个基于vue.js进行快速开发的完整系统。使用Vue脚手架之后开发页面将是一个完整系统(项目)

15.3Vue CLI优势

  • 通过 @vue/cli 实现的交互式的项目脚手架。

  • 通过 @vue/cli + @vue/cli-service-global 实现的零配置原型开发。

    vue页面 vue.js vue-axios vue-router(一条命令) 都包含

  • 一个运行时依赖 (@vue/cli-service

    • 可升级; 一条命令
    • 基于 webpack 构建,并带有合理的默认配置;webpack项目打包方式 编译好的项目源码=>部署直接可用
    • 可以通过项目内的配置文件进行配置; 默认配置文件,通过改默认配置文件达到想要的项目环境
    • 可以通过插件进行扩展。 vue v-charts elementui
    • 一个丰富的官方插件集合,集成了前端生态中最好的工具。Node.js(类似tomcat) Vue VueRouter webpack yarn
  • 一套完全图形化的创建和管理 Vue.js 项目的用户界面。

15.4Vue CLI安装

1.环境准备

npm类似于maven node.js类似于tomcat

vue cli3安装以以下为准 也可参考链接:https://blog.csdn.net/xuwei1215225/article/details/89519600

node.js对应npm版本:https://nodejs.org/zh-cn/download/releases/

# 1.npm介绍
	node package manager  //简称npm。  node.js包管理工具  前端主流技术  npm进行统一管理
	maven管理java后端依赖 远程仓库(中心仓库)  阿里云镜像
	npm  管理前端系统依赖 远程仓库(中心仓库)  配置淘宝镜像
npm 是 Node.js 官方提供的包管理工具,用于 Node.js 包的发布、传播、依赖控制。npm 提供了命令行工具,使你可以方便地下载、安装、升级、删除包,也可以让你作为开发者发布并维护包。

# 2.下载node.js 
 Vue CLI 需要 Node.js 8.9 或更高版本 (推荐 8.11.0),此处在网上下载的node.15.0.1版
    node.js中文网  http://nodejs.cn/download/
    windows系统: .msi(安装包 exe)安装指定位置    .zip(压缩包) 解压缩至指定目录
    mac os 系统: .pkg 安装包格式自动配置环境变量  .tar.gz(压缩包) 解压缩至指定目录
# 3.配置node.js环境变量 (安装一般会自动配置)
	桌面 计算机=>右键属性=>高级属性=>环境变量 添加如下配置
	系统变量=>选择Path 编辑 新建  直接输入node.js目录即可
# 4.cmd命令验证是否安装成功
	node -v  输出node版本安装成功,如失败参考网上资料安装配置
	npm  -v  查看npm版本
# 5.配置淘宝镜像*
	百度搜索 npm淘宝镜像,通过命令配置安装
  配置命令:npm config set registry https://registry.npm.taobao.org

  验证镜像是否成功:npm config get registry
# 6.配置npm下载依赖的位置
	npm config ls  执行后看到默认下载cache和prefix是C盘	
	
	1.npm config set cache "D:\node.js\cli_path\npm-cache" (更改为创建文件的路径)
	2.npm config set prefix "D:\node.js\cli_path\npm-global"
	配置之后,在执行第一条命令,可看到默认下载路径已更改
	
    
	npm config ls  再次验证node.js默认依赖位置

    ;userconfig C:\Users\user\.npmrc
    cache = "D:\\node.js\\cli_path\\npm-cache"
    prefix = "D:\\node.js\\cli_path\\npm-global"
    registry = "https://registry.npm.taobao.org1/"
    sass-binary_site = "https:npm.taobao.org/mirrors/node-sass"
    sass_binary_site = "https://npm.taobao.org/mirrors/node-sass"
    
    输出以上内容 成功

2.安装脚手架

# 安装Vue-CLI
 	npm install @vue/cli -g  (cli3的版本) 此处安装是3版本
	npm install vue-cli -g   (cli2的版本)
	
# 卸载脚手架
    npm uninstall -g @vue/cli   //卸载3.x版本脚手架
    npm uninstall -g vue/cli    //卸载2.x版本脚手架

3.第一个vue脚手架项目

# 1.创建vue脚手架第一个项目
    在要创建项目路径的通过如下命令创建
    vue init webpack 项目名      回车执行
# 2.项目结构
	v_project            --->项目名
	 -build			       ---> 使用webpack打包使用build依赖
	 -config		       ---> 整个项目配置目录
	 -src			       ---> 编写vue的源代码[重点]
	   - assets		         ---> 存放静态资源[重点]
	   - components          ---> 写Vue组件[重点]
	   - router		         ---> 配置项目中的路由[重点]
	   - App.vue	         ---> 项目中根组件[重点]
	   - main.js             ---> 项目的主路口[重点]
	 -static		       ---> 其它静态
	 -.babelrc		       ---> 将ES6语法转为ES5运行
	 -.editorconfig	       --->项目编辑配置
	 -.gitignore	       --->git版本控制忽略文件
	 -.postcssrc.js	       --->源码相关js
	 -index.html	       --->项目主页
	 -package.json 	       --->类似pom.xml  依赖管理  不建议手动更改
	 -package-lock.json    --->对package.json枷锁
	 -README.md            --->项目说明文件
# 3.运行脚手架项目(进入当前项目文件) 
	npm start    
	npm run dev
	两种命令都可以
运行之后 根据提供的路径端口访问 默认 http://localhost:8080
# 4. 查看可以基于哪些模板创建vue应用程序,通常选择 webpack
	vue list  //作用意义不大
# 5.Vue Cli中项目开发方式
	一切皆组件  一个组件中   js代码   html代码  css样式
   1.VueCli开发方式是在项目中开发一个一个组件对应一个业务功能模块,之后可将多个组件组合在一起构成前端系统
   2.在使用Vue Cli开发时,不在书写html,编写的是一个组件(.vue结尾的文件),打包时vue cli会将组件编译成运行的html文件

15.5如何开发vue脚手架

Vue cli中一切皆组件

15.6在脚手架中使用axios

安装axios

npm install axios --save-dev

**配置axios 在项目main.js引入axios **

import axios from 'axios';

使用axios

	在需要发送异步请求的位置: 
	this.$http.get("url").then((res)=>{})
	this.$http.post("url").then((res)=>{})

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bh5vNXaa-1616920135873)(D:/typora/Typora/img/vue/1616895946689.png)]

16.vue cli crud案例

前端实例

前后端分离,结合springboot开发

项目结构

在这里插入图片描述

运行效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ej1LIxDj-1616920135883)(D:/typora/Typora/img/vue/1616919134853.png)]

创建脚手架项目

在需要创建项目的文件夹使用 idea命令行终端 或在文件夹 输入以下命令构建项目

vue init webpack 项目名

创建完成后删除 components组件的内容,删除之后创建我们自己的5个组件

此项目中只用到了如下代码内容,简易增删改查开发,其余文件均未修改

Home.vue
<template>
    <div>
      <h1>欢迎进入</h1>
    </div>
</template>

<script>
    export default {
        name: "Home"
    }
</script>

<style scoped>

</style>

Student.vue
<template>
    <div>
      <h1>学生管理</h1>
    </div>
</template>

<script>
    export default {
        name: "Student"
    }
</script>

<style scoped>

</style>

User.vue
<template>
  <div>
    <h1>用户列表</h1>
    <table border="1">
      <tr>
        <td>编号</td>
        <td>姓名</td>
        <td>年龄</td>
        <td>生日</td>
        <td>操作</td>
      </tr>
      <tr v-for="user in users">
        <td>{{user.id}}</td>
        <td>{{user.name}}</td>
        <td>{{user.age}}</td>
        <td>{{user.bir}}</td>
        <td><a href="javascript:;" @click="delRow(user.id)">删除</a> <a :href="'#/user/edit?id='+user.id">修改</a></td>
      </tr>
    </table>
    <a href="#/user/add">添加</a>
    <router-view></router-view>
  </div>
</template>

<script>
  export default {
    name: "User",
    data() {
      return {
        users:[]
      }
    },
    methods: {
      findAll(){//查询所有
        this.$http.get("http://localhost:8989/vue/user/findAll?page=1&row=4").then((res)=>{
          console.log(res.data)
          this.users = res.data.result;
        })
      },
      delRow(id){//删除
        console.log(id);
        this.$http.get("http://localhost:8989/vue/user/delete?id="+id).then((res)=>{
          if (confirm("确认删除"+id+"吗?")){
            if(res.data.state){
              alert("删除"+id+"成功");
              this.findAll();
            }
          }
        })
      }
    },
    created() {
      this.findAll();
    },
    watch:{ //用来监听路由变化
      $route:{
        handler:function (val,oldVal) {
          console.log(val);
          if(val.path=='/user'){
            this.findAll();
          }
        },
        //深度观察监听
        deep:true
      }
    }
  }
</script>

<style scoped>

</style>
UserAdd.vue
<template>
  <div>
    <h2>用户信息添加</h2>
    <form>
      用户名:<input type="text" v-model="user.name"><br>
      年龄:<input type="text" v-model="user.age"><br>
      生日:<input type="text" v-model="user.bir"><br>
      <input type="button" value="添加" @click="saveUserInfo()">
    </form>
  </div>
</template>

<script>
  export default {
    name: "UserAdd",
    data() {
      return {
        user: {},
      }
    },
    methods: {
      saveUserInfo() {
        //发送axios请求 添加数据
        console.log(this.user);
        this.$http.post("http://localhost:8989/vue/user/add", this.user).then((res) => {
          if (res.data.state) {
            this.$router.push("/user");//数据添加至用户页的路由
          }
        })
      }
    }
  }
</script>

<style scoped>

</style>

UserEdit.vue
<template>
  <div>
    <h2>编辑信息</h2>
    <form action="">
      用户名:<input v-model="user.name" type="text">
      年龄:<input v-model="user.age" type="text">
      生日:<input v-model="user.bir" type="text"><br>
      <input type="button" @click="editUserInfo()" value="提交">
    </form>
  </div>
</template>

<script>
  export default {
    name: "UserEdit",
    data() {
      return {
        user: {
          id: "",
        }
      }
    },
    methods: {
      findOne() {//查询一个内容
        this.$http.get("http://localhost:8989/vue/user/findOne?id=" + this.user.id).then((res) => {
          this.user = res.data;
        });
      },
      editUserInfo() {
        this.$http.post("http://localhost:8989/vue/user/update", this.user).then((res) => {
          console.log(res);
          if (res.data.state) {
            this.$router.push("/user");//切换路由
          }
        });
      }
    },
    created() {
      console.log("修改组件id:" + this.$route.query.id);
      this.user.id = this.$route.query.id;
      this.findOne();

    }
  }
</script>

<style scoped>

</style>

router/index.js路由配置
import Vue from 'vue'
import Router from 'vue-router'
import Home from "../components/Home";
import User from "../components/User";
import Student from "../components/Student";
import UserAdd from "../components/UserAdd";
import UserEdit from "../components/UserEdit";
Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      redirect:'Home'
    },
    {
      path: '/home',
      component: Home
    },
    {
      path: '/user',
      component: User,
      children:[
        {
          path:'add',
          component:UserAdd //嵌套路由 用户添加
        },
        {
          path: 'edit',
          component: UserEdit
        }
      ]
    },
    {
      path: '/student',
      component: Student
    },
  ]
})
App.vue
<template>
  <div id="app">
    <router-link to="/home">主页</router-link>
    <router-link to="/user">用户管理</router-link>
    <router-link to="/student">学生管理</router-link>
    <router-view/>
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>

<style>

</style>

后端实例

后端给前端提供数据,前端请求后端给予响应

项目结构

在这里插入图片描述

准备sql
/*
SQLyog Ultimate v12.3.1 (64 bit)
MySQL - 5.7.20-log : Database - stu_newest
*********************************************************************
*/


/*!40101 SET NAMES utf8 */;

/*!40101 SET SQL_MODE=''*/;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`stu_newest` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `stu_newest`;

/*Table structure for table `v_pro` */

DROP TABLE IF EXISTS `v_pro`;

CREATE TABLE `v_pro` (
  `id` int(6) NOT NULL AUTO_INCREMENT,
  `name` varchar(40) DEFAULT NULL,
  `age` int(4) DEFAULT NULL,
  `bir` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;

/*Data for the table `v_pro` */

insert  into `v_pro`(`id`,`name`,`age`,`bir`) values 

(1,'admin',15,'2021-03-28 13:33:20'),

(8,'tizi',21,'1999-07-06 08:00:00'),

(9,'idea test',0,'1999-03-05 08:00:00');

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

User实体
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Accessors(chain = true)
public class User {
    private Integer id;
    private String name;
    private Integer age;
    @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GTM+8")
    private Date bir;
}
UserMapper
@Mapper
public interface UserMapper {
    //添加
    void save(User user);

    //查出一个值
    User findById(Integer id);
    //修改
    void update(User user);

    //删除
    void delete(Integer id);

    //查询所有值
    public List<User> findAll();
}

UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace=绑定一个指定的dao/mapper接口-->
<mapper namespace="com.lemon.dao.UserMapper">
    <!--查询所有的值-->
    <select id="findAll" resultType="user">
        select id,name,age,bir from v_pro
    </select>

    <select id="findById" resultType="user">
        SELECT id,NAME,age, bir FROM v_pro WHERE id = #{id}
    </select>

    <update id="update" parameterType="user">
        update v_pro
        set name=#{name},age=#{age},bir=#{bir}
        where id = #{id}
    </update>

    <delete id="delete" parameterType="integer">
        delete from v_pro where id = #{id}
    </delete>

    <insert id="save" parameterType="user" useGeneratedKeys="true" keyProperty="id">
        insert into v_pro values (#{id},#{name},#{age},#{bir})
    </insert>
</mapper>
UserService
public interface UserService {
    //添加
    void save(User user);

    //查出一个值
    User findById(Integer id);
    //修改
    void update(User user);

    //删除
    void delete(Integer id);

    //查询所有值
    public List<User> findAll();
}

UserServiceImpl
@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserMapper userMapper;

    @Override
    public void save(User user) {
        userMapper.save(user);
    }

    @Override
    public User findById(Integer id) {
        return userMapper.findById(id);
    }

    @Override
    public void update(User user) {
        userMapper.update(user);
    }

    @Override
    public void delete(Integer id) {
        userMapper.delete(id);
    }

    @Override
    public List<User> findAll() {
        return userMapper.findAll();
    }
}
application.properties
spring.application.name=vue
server.port=8989
server.servlet.context-path=/vue

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/stu_newest?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=12345678

mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
mybatis.type-aliases-package=com.lemon.entity

logging.level.root=info
logging.level.com.lemon.dao=debug
UserController控制器
@RestController
@CrossOrigin
@RequestMapping("/user")
public class UserController {
    @Resource
    private UserService userService;

    /**
     * 更新值
     */
    @PostMapping("/update")
    public Map<String, Object> update(@RequestBody User user) {
        Map<String, Object> map = new HashMap<>();
        try {
            userService.update(user);
            map.put("state", true);
            map.put("msg", "修改成功");
        } catch (Exception e) {
            map.put("state", false);
            map.put("msg", "修改失败: " + e.getMessage());
        }


        return map;
    }

    /**
     * 查询一个
     */
    @GetMapping("/findOne")
    public User findOne(Integer id) {
        return userService.findById(id);

    }

    /**
     * 删除用户
     */
    @GetMapping("/delete")
    public Map<String, Object> delete(Integer id) {
        System.out.println("删除id:" + id);
        Map<String, Object> map = new HashMap<>();
        try {
            userService.delete(id);
            map.put("state", true);
            map.put("msg", "删除成功");
        } catch (Exception e) {
            e.printStackTrace();
            map.put("state", false);
            map.put("msg", "删除失败: " + e.getMessage());
        }

        return map;
    }

    /**
     * 添加用户
     */
    @PostMapping("/add")
    public Map<String, Object> add(@RequestBody User user) {
        System.out.println("front user: " + user);
        Map<String, Object> map = new HashMap<>();
        try {
            userService.save(user);
            map.put("state", true);
            map.put("msg", "添加成功");
        } catch (Exception e) {
            e.printStackTrace();
            map.put("state", false);
            map.put("msg", "添加失败: " + e.getMessage());
        }
        return map;
    }

    /**
     * 查询所有
     *
     * @return
     */
    @GetMapping("/findAll")
    public Map<String, Object> findAll(Integer page, Integer rows) {
        Map<String, Object> map = new HashMap<>();
        List<User> result = userService.findAll();
        map.put("total", 10);
        map.put("totalPage", 1);
        map.put("page", 1);
        map.put("result", result);
        return map;
    }
}

17.vue cli脚手架项目打包和部署

# 1.在前端项目的根目录中 执行如下命令即可打包
	npm run build
	
    注意vue脚手架打包的项目必须在服务器上运行,不能直接双击运行
# 2.打包之后项目中变化
	在打包之后项目中出现dist目录,此目录就是vue脚手架项目的生产目录 或者 说是直接部署目录

打包成功之后当前项目会多出一个dist目录,将dist目录复制到idea static文件目录,修改index.html页面配置,直接也可运行

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n7Hh9ZX3-1616920135889)(D:/typora/Typora/img/vue/1616919899347.png)]

在这里插入图片描述
运行完成,此文章总结完毕,感谢您的参考和观看 thank~


该文章是vue进阶篇
入门篇链接地址 https://blog.csdn.net/qq_41157588/article/details/115085686 ,代码很全 供学习参考,更直观了解vue+springboot结合开发

需要全套源码及pdf文件 请 评论留言 或 发送邮箱至 ti66666@vip.qq.com

vue进阶篇总结到此结束,一字字总结不易,点个赞收藏评论支持下,你的支持是我创造的动力,thank~

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值