# springboot+vue+tkmapper **Repository Path**: guancg/springboot-vue-tkmapper ## Basic Information - **Project Name**: springboot+vue+tkmapper - **Description**: vue-vue-vue-vue - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 5 - **Forks**: 1 - **Created**: 2021-05-18 - **Last Updated**: 2022-08-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # springboot+vue+tkmapper # spring boot 集成 swagger 3.0 指南 > 1. 导入依赖 > > ~~~xml > > io.springfox > springfox-boot-starter > 3.0.0 > > > > com.github.xiaoymin > swagger-bootstrap-ui > 1.9.6 > > ~~~ > > 2. 自定义配置类信息 > > ~~~java > package tech.guan.config; > > import org.springframework.context.annotation.Bean; > import org.springframework.context.annotation.Configuration; > import springfox.documentation.builders.ApiInfoBuilder; > import springfox.documentation.builders.PathSelectors; > import springfox.documentation.builders.RequestHandlerSelectors; > import springfox.documentation.service.ApiInfo; > import springfox.documentation.service.Contact; > import springfox.documentation.spi.DocumentationType; > import springfox.documentation.spring.web.plugins.Docket; > import springfox.documentation.swagger2.annotations.EnableSwagger2; > > /** > * 本类用来演示: - http://localhost:8080/swagger-ui/index.html > * > * @author: success > * @date: 2021/5/17 10:52 上午 > */ > @Configuration > public class SwaggerConfig{ > /*swagger会帮助我们生成接口文档 > * 1:配置生成的文档信息 > * 2: 配置生成规则*/ > > /*Docket封装接口文档信息*/ > @Bean > public Docket getDocket(){ > > //创建封面信息对象 > ApiInfoBuilder apiInfoBuilder = new ApiInfoBuilder(); > apiInfoBuilder.title("《亲爱的小管》后端接口说明") > .description("此文档详细说明了锋迷商城项目后端接口规范....") > .version("v 2.0.1") > .contact( new Contact("success","www.google.com","849962874@qq.com") ); > ApiInfo apiInfo = apiInfoBuilder.build(); > > Docket docket = new Docket(DocumentationType.SWAGGER_2) > .apiInfo(apiInfo) //指定生成的文档中的封面信息:文档标题、版本、作者 > .select() > .apis(RequestHandlerSelectors.basePackage("tech.guan.controller")) > .paths(PathSelectors.any()) > .build(); > > return docket; > } > } > ~~~ > > 3. 主入口程序添加EnableOpenApi注解 > > ~~~java > package tech.guan; > > //import org.mybatis.spring.annotation.MapperScan; > import org.mybatis.spring.annotation.MapperScan; > import org.springframework.boot.SpringApplication; > import org.springframework.boot.autoconfigure.SpringBootApplication; > import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; > import springfox.documentation.oas.annotations.EnableOpenApi; > > > @EnableOpenApi > @MapperScan("tech.guan.mapper") > @SpringBootApplication > public class ApiApplication { > > public static void main(String[] args) { > SpringApplication.run(ApiApplication.class, args); > } > } > > ~~~ ## Swagger3.0注解使用说明 > @Api:用在请求的类上,表示对类的说明 > tags="说明该类的作用,可以在UI界面上看到的注解" > value="该参数没什么意义,在UI界面上也看到,所以不需要配置" > > @ApiOperation:用在请求的方法上,说明方法的用途、作用 > value="说明方法的用途、作用" > notes="方法的备注说明" > > @ApiImplicitParams:用在请求的方法上,表示一组参数说明 > @ApiImplicitParam:用在@ApiImplicitParams注解中,指定一个请求参数的各个方面 > name:参数名 > value:参数的汉字说明、解释 > required:参数是否必须传 > paramType:参数放在哪个地方 > · header --> 请求参数的获取:@RequestHeader > · query --> 请求参数的获取:@RequestParam > · path(用于restful接口)--> 请求参数的获取:@PathVariable > · body(不常用) > · form(不常用) > dataType:参数类型,默认String,其它值dataType="Integer" > defaultValue:参数的默认值 > > @ApiResponses:用在请求的方法上,表示一组响应 > @ApiResponse:用在@ApiResponses中,一般用于表达一个错误的响应信息 > code:数字,例如400 > message:信息,例如"请求参数没填好" > response:抛出异常的类 > > @ApiModel:用于响应类上,表示一个返回响应数据的信息 > (这种一般用在post创建的时候,使用@RequestBody这样的场景, > 请求参数无法使用@ApiImplicitParam注解进行描述的时候) > @ApiModelProperty:用在属性上,描述响应类的属性 ## 案例 > 1. UserController控制层 > > ~~~java > package tech.guan.controller; > > import io.swagger.annotations.Api; > import io.swagger.annotations.ApiImplicitParam; > import io.swagger.annotations.ApiImplicitParams; > import io.swagger.annotations.ApiOperation; > import org.springframework.beans.factory.annotation.Autowired; > import org.springframework.web.bind.annotation.GetMapping; > import org.springframework.web.bind.annotation.PostMapping; > import org.springframework.web.bind.annotation.RequestMapping; > import org.springframework.web.bind.annotation.RestController; > import tech.guan.mapper.UsersMapper; > import tech.guan.vo.ResStatus; > import tech.guan.vo.ResultVO; > > /** > * 本类用来演示: > * > * @author: success > * @date: 2021/5/17 1:45 下午 > */ > @Api(value = "用户控制层接口",tags = "用户管理") > @RestController > @RequestMapping("/user") > public class UserController { > > @Autowired > private UsersMapper usersMapper; > > @GetMapping > public String hello(){ > System.out.println(usersMapper.findAll()); > return "ok"; > } > > //测试swagger注解 > @ApiOperation("用户登录接口") > @ApiImplicitParams({ > @ApiImplicitParam(name = "username",type = "String",value = "用户登录账号",required = true), > @ApiImplicitParam(name = "password",type = "String",value = "用户登录密码",required = true) > } > ) > @PostMapping("/login") > public ResultVO login(String username,String password){ > if("admin".equals(username) && "admin".equals(password)){ > return new ResultVO(ResStatus.OK,"登录成功",null); > } > return new ResultVO(ResStatus.NO,"登录失败",null); > } > } > ~~~ > > 2. ResultVo对象 > > ~~~java > package tech.guan.vo; > > import io.swagger.annotations.ApiModel; > import io.swagger.annotations.ApiModelProperty; > import lombok.AllArgsConstructor; > import lombok.Data; > import lombok.NoArgsConstructor; > > import javax.annotation.Resource; > > @Data > @NoArgsConstructor > @AllArgsConstructor > @ApiModel(value = "ResultVO对象",description = "封装接口返回给前端的数据") > public class ResultVO { > > //响应给前端的状态码 > @ApiModelProperty(value = "响应状态码",dataType = "int") > private int code; > > //响应给前端的提示信息 > @ApiModelProperty("响应提示信息") > private String msg; > > //响应给前端的数据 > @ApiModelProperty("响应数据") > private Object data; > } > ~~~ ## 测试 > 启动项目输入http://localhost:8080/swagger-ui/index.html > > ![](imgs/swagger-ui.png) > > > > 或者http://localhost:8080/doc.html > > ![](imgs/bootstrap-ui.png) ## 注意细节 > 添加swagger之后,有可能导致原来的springboot工程下的src/main/resources目录下的static目录中的静态资源访问不了.需要在项目中添加配置类 ~~~java package tech.guan.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * 本类用来演示: * * @author: success * @date: 2021/5/17 1:53 下午 */ //https://github.com/ruiyeclub/SpringBoot-Hello @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/"); // 解决静态资源无法访问 registry.addResourceHandler("/**") .addResourceLocations("classpath:/","classpath:/static/"); // 解决swagger无法访问 // registry.addResourceHandler("/swagger-ui.html") // .addResourceLocations("classpath:/META-INF/resources/"); // // 解决swagger的js文件无法访问 // registry.addResourceHandler("/webjars/**") // .addResourceLocations("classpath:/META-INF/resources/webjars/"); } } ~~~ # tkMapper插件使用 ## 简介 > 基于MyBatis提供了很多第三方插件,这些插件通常可以完成数据操作方法的封装(GeneralDAO)、数据库逆向工程工作(根据数据表生成实体类、生成映射文件) > > - MyBatis-plus > - tkMapper > tkMapper就是一个MyBatis插件,是在MyBatis的基础上提供了很多工具,让开发变得简单,提高开发效率。 > > - 提供了针对单表通用的数据库操作方法 > - 逆向工程(根据数据表生成实体类、dao接口、映射文件) ## 整合tkMapper > 1. 添加依赖 > > ~~~xml > > > tk.mybatis > mapper-spring-boot-starter > 2.1.5 > > ~~~ > > 2. 修改启动类的`@MapperScan`注解的包 > > ```java > import tk.mybatis.spring.annotation.MapperScan; > > @EnableOpenApi > @MapperScan("tech.guan.mapper") > ``` > 3. 需要使用到的俩个接口是Mapper和MySqlMapper > > 我们可以制定一个通用接口来继承这俩个接口 > > ~~~java > package tech.guan.mapper; > > import tech.guan.pojo.Users; > import tk.mybatis.mapper.common.Mapper; > import tk.mybatis.mapper.common.MySqlMapper; > > /** > * 本类用来演示: 通用的接口 > * > * @author: success > * @date: 2021/5/18 9:42 上午 > */ > public interface GenericDao extends Mapper, MySqlMapper { > } > > 注意:通用接口不能放在主程序注解@MapperScan扫描的包中,否则会抛出TypeVariableImpl cannot be cast to java.lang.Class异常 > ~~~ > > 4. 自定义UserMapper来继承GenericDao > > ~~~java > package tech.guan.mapper; > > import org.apache.ibatis.annotations.Select; > import tech.guan.pojo.Users; > > import java.util.List; > > /** > * 本类用来演示: 用户mapper > * > * @author: success > * @date: 2021/5/17 10:15 上午 > */ > public interface UsersMapper extends GenericDao{ > > } > > package tech.guan.mapper; > > ====================================================== > > import tech.guan.pojo.Category; > > /** > * 本类用来演示: 商品类别Mapper > * > * @author: success > * @date: 2021/5/18 9:51 上午 > */ > public interface CategoryMapper extends GenericDao { > } > > ~~~ ## tkMapper提供的常用方法 > 1. 插入 - 不返回主键值 > > ~~~java > @Test > public void testInsertNoId(){ > Category category = new Category(0,"测试类别3",1,0,"03.png","xixi","aaa.jpg","black"); > categoryMapper.insert(category); > System.out.println("id:"+category.getCategoryId()); > } > ~~~ > > 2. 插入 - 返回主键值 > > ~~~java > /** > * 插入之后返回主键值 > */ > @Test > public void testInsertNoId(){ > Category category = new Category(0,"测试类别4",1,0,"03.png","xixi","aaa.jpg","black"); > //categoryMapper.insert(category);//不返回主键值 > categoryMapper.insertUseGeneratedKeys(category);//返回刚刚插入得到的主键值 - 主键值回显 > System.out.println(category.getCategoryId()); > } > 这个时候需要在Catagory的categoryId属性上增加@Id的注解,指明这个属性字段对应数据库的primary key,才能成功,否则失败 > @Id > private Integer categoryId; > ~~~ > > 3. 根据主键进行更新操作 > > ~~~java > /** > * 根据主键值查询 > * 1. 先根据主键值查询 > * 2. 再根据主键值更新 > */ > @Test > public void testUpdateByPrimaryKey(){ > //根据主键值id进行查询 > Category category = new Category(); > category.setCategoryId(52); > Category c = categoryMapper.selectByPrimaryKey(category); > c.setCategoryName("success"); > categoryMapper.updateByPrimaryKey(c); > } > ~~~ > > 4. 查询所有的 > > ~~~java > /** > * 查询所有的 > */ > @Test > public void testFindAll(){ > categoryMapper.selectAll().forEach(e-> System.out.println(e)); > } > ~~~ > > 5. 根据主键值进行删除 > > ~~~java > /** > * 根据主键值删除 > */ > @Test > public void testDeleteByPrimaryKey(){ > Category category = new Category(); > category.setCategoryId(52); > categoryMapper.deleteByPrimaryKey(category); > } > ~~~ ## 条件查询 > 1. 案例01 > > ~~~java > /** > * 条件查询 > */ > @Test > public void testByExample(){ > Example example = new Example(Category.class); > Example.Criteria criteria = example.createCriteria(); > criteria.andEqualTo("categoryLevel",1); > > categoryMapper.selectByExample(example).forEach(e-> System.out.println(e)); > } > ~~~ > > 2. 模糊查询 > > ~~~java > /** > * 模糊查询 > */ > @Test > public void testByExample2(){ > Example example = new Example(Category.class); > Example.Criteria criteria = example.createCriteria(); > criteria.andEqualTo("categoryLevel",1) > .orLike("categoryName","%干%"); > > categoryMapper.selectByExample(example).forEach(e-> System.out.println(e)); > } > ~~~ ## 条件分页查询 ~~~java /** * 条件分页查询 */ @Test public void testByExampleAndPage(){ Example example = new Example(Category.class); Example.Criteria c = example.createCriteria(); c.andEqualTo("categoryLevel",1); //模拟分页的数据 int pageSize = 3;//每页显示条数 int pageNum=2;//当前页 int startPage = (pageNum-1)*pageSize;//起始页 RowBounds rowBounds = new RowBounds(startPage,pageSize); List list = categoryMapper.selectByExampleAndRowBounds(example,rowBounds); for (Category category : list) { System.out.println(category); } } ~~~ ## 关联查询 > 1. 所有的关联查询都是通过多个单表操作来实现 > > ~~~java > //查询用户同时查询订单 > Example example = new Example(User.class); > Example.Criteria criteria = example.createCriteria(); > criteria.andEqualTo("username","zhangsan"); > //根据用户名查询用户 > //1.先根据用户名查询用户信息 > List users = userDAO.selectByExample(example); > User user = users.get(0); > //2.再根据用户id到订单表查询订单 > Example example1 = new Example(Orders.class); > Example.Criteria criteria1 = example1.createCriteria(); > criteria1.andEqualTo("userId",user.getUserId()); > List ordersList = orderDAO.selectByExample(example1); > //3.将查询到订单集合设置到user > user.setOrdersList(ordersList); > > System.out.println(user); > ~~~ > > 2. 自定义查询 > > ~~~java > 在使用tkMapper,DAO继承Mapper和MySqlMapper之后,还可以自定义查询 > public interface UserDAO extends GeneralDAO { > > public User selectByUsername(String username); > > } > ~~~ > > 创建mapper文件 > > ~~~xml > > PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" > "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> > > > > insert into users(username,password,user_img,user_regtime,user_modtime) > values(#{username},#{password},#{userImg},#{userRegtime},#{userModtime}) > > > > > > > > > > > > > > > > > > > > ~~~ ## 逆向工程 > 简介 - 逆向工程,根据创建好的数据表,生成实体类、DAO、映射文件 > 1. 在src/main/resources的generator目录中创建generatorConfig.xml > > ~~~xml > > PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" > "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> > > > > > > > > > > > > > > > > connectionURL="jdbc:mysql://localhost:3306/vue" > userId="root" password="root"> > > > > > > > > > > > > > > > >
> > > > > > > > >
>
> 2. 添加依赖 > > ~~~xml > > xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" > xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> > > mall-demo > tech.guan > 0.0.1-SNAPSHOT > > 4.0.0 > > generator > > > tk.mybatis > mapper-spring-boot-starter > 2.1.5 > > > > > > org.mybatis.generator > mybatis-generator-maven-plugin > 1.3.5 > > ${basedir}/src/main/resources/generator/generatorConfig.xml > > > > mysql > mysql-connector-java > 5.1.47 > > > tk.mybatis > mapper > 4.1.5 > > > > > > > ~~~ # Vue简介 ## Jquery的复杂性问题 - 使用jQuery进行前后端分离开发,既可以实现前后端交互(ajax),又可以完成数据渲染; - 存在的问题:jQuery需要通过HTML标签拼接、DOM节点操作完成数据的显示,开发效率低且容易出错,渲染效率较低 - vue 是继jQuery之后的又一优秀的前端框架:专注于前端数据的渲染——语法简单、渲染效率高 ## VUE简介 ### 前端框架 - 前端三要素:HTML、CSS、JavaScript - HTML决定网页结构 - CSS决定显示效率 - JavaScript决定网页功能(交互、数据显示) - UI框架: - Bootstrap - amazeUI - Layui - JS框架: - jQuery(jQuery UI) - React - angular - nodejs----后端开发 - vue 集各种前端框架的优势发展而来 ### MVVM > 项目结构经历的三个阶段: **后端MVC** 我们就可以理解为单体架构,流程控制是由后端控制器来完成 **前端MVC** 前后端分离开发,后端只负责接收响应请求 **MVVM** 前端请求后端接口,后端返回数据,前端接收数据,并将接收的数据设置“VM”,HTML从vm取值 - M model 数据模型 指的是后端接口返回的数据 - V view 视图 - VM ViewModel 视图模型 数据模型与视图之间的桥梁,后端返回的model转换前端所需的vm,视图层可以直接从vm中提取数据 # Vue入门使用 > vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合. > vue的引入 > > 1. 离线引用:下载vue的js文件,添加到前端项目,在网页中通过script标签引用vue.js文件 > 2. CDN引用: ## 声明式渲染 ~~~html
{{msg}}
~~~ > 1. 渲染基本数据类型和字符串 > > > ~~~html > > > > > > > > > > > > > > Document > > > > > > > >
> > {{id}}
> > {{msg}}
> > > > {{student.stuName}} > >
> > > > > > > > > > ~~~ ## v-if以及v-for的入门使用 > ~~~html > > > > > > > Document > > > >
> > > > > > > > > > > > > > > > > > > >
序号学号姓名性别年龄
{{index+1}}{{s.stuNum}}{{s.stuName}}{{s.stuGender=='M'?'男':'女'}}{{s.stuAge}}
>
> > > > ~~~ ## v-bind绑定标签属性 ~~~html Document


~~~ ## v-model > 表单的双向绑定 - 只能使用在表单输入标签 - v-model:value 可以简写为 v-model ~~~html Document
{{msg}}
~~~ # Vue实例 > 每个使用vue进行数据渲染的网页文档都需要创建一个Vue实例 —— ViewModel ## Vue实例的生命周期 > vue实例生命周期——vue实例从创建到销毁的过程 - 创建vue实例(初始化data、加载el) - 数据挂载(将vue实例data中的数据渲染到网页HTML标签) - 重新渲染(当vue的data数据发生变化,会重新渲染到HTML标签) - 销毁实例 ## 钩子函数 为了便于开发者在vue实例生命周期的不同阶段进行特定的操作,vue在生命周期四个阶段的前后分别提供了一个函数,这个函数无需开发者调用,当vue实例到达生命周期的指定阶段会自动调用对应的函数。 ![](imgs/vue/lifecycle.png) ~~~html Document
~~~ # Vue计算属性和侦听器 ## 计算属性 > * data中的属性可以通过声明获得,也可以通过在computed通过计算获得 > > * 特性:计算属性所依赖的属性值发生变化会影响计算属性的值同时发生变化 > > ~~~html > > > > > > > Document > > >
> > > {{count3}} >
> > > > > > ~~~ ## 侦听器 > ~~~html > > > > > > > Document > > > >
> > > {{count3}} >
> > > > > ~~~ # class与style绑定 > 我们可以使用mustache语法将vue中data的数据绑定到HTML标签及标签的属性,如何将data中的值绑定到标签的class及style属性呢? ## class绑定 ~~~html Document



~~~ ## style绑定 ~~~html Document
亲爱的小管
亲爱的小管
亲爱的小管
亲爱的小管
~~~ # 条件与列表渲染 ## 条件渲染 ### 1. v-if使用 > 在html标签可以添加v-if指令指定一个条件,如果条件成立则显示此HTML标签,如果不成立则不显示当前标签; > > 条件可以是一个表达式也可以是一个具体的bool类型值 ~~~html Document

可以看见我是可爱的小管

看不到我

~~~ ### 3. v-else使用 > 注意点:v-else标签需要紧跟在v-if的标签之后,中间不能有其他标签 ~~~html Document

可以看见我是可爱的小管

看不到我

嘿嘿

~~~ ### 3. v-else-if ~~~html Document

可以看见我是可爱的小管

看不到我

嘿嘿


优秀

良好

中等

及格

不想理你

~~~ ### 4. v-if和v-show区别 > 从功能上将v-show和v-if作用是相同的,渲染过程有区别 > `v-if` 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。 > > `v-if` 也是**惰性的**:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。 > > 相比之下,`v-show` 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。 > > 一般来说,`v-if` 有更高的切换开销,而 `v-show` 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 `v-show` 较好;如果在运行时条件很少改变,则使用 `v-if` 较好。 ## 列表渲染 > 将集合数据以表格、列表的形式显示 ~~~html Document
  1. {{c.cname}}

序号 学号 照片 姓名 性别 年龄 操作
~~~ # 事件处理 > - 在使用vue进行数据渲染时,如果使用原生js事件绑定(例如onclick),如果需要获取vue实例中的数据并传参则需要通过拼接来完成 > - vue提供了v-on指令用于绑定各种事件(v-on:click),简化了从vue取值的过程,但是触发的方法需要定义在vue实例的 methods中 > - `v-on:click可以缩写为`@click` ## hello案例 ~~~html
~~~ ## 原生js函数传值 ~~~html Document
~~~ ## 使用dataset对象传值 ~~~html Document
~~~ ## 混合使用 > js函数传值和dataset对象传值,俩者混合使用 ~~~html Document
~~~ # 事件修饰符 > 当使用v-on进行事件绑定的时候,可以添加特定后缀,设置事件触发的特性 > 事件修饰符使用示例 > >~~~html > >~~~ > 1. **.prevent** 消除元素的默认事件 > > ~~~html > > > > > > > Document > > > >
>
> >
>
> > > > > ~~~ > > 2. 阻止事件冒泡(阻止子标签向上冒泡) > > 3. 设置只能自己触发事件(子标签不能触发) > > ~~~html > > > > > > > Document > > > >
>
> >
>
>
>
> >
>
>
> > > > > ~~~ > 4. .once - 限定事件只触发一次 ## 按键修饰符 > 按键修饰符就是针对键盘事件的修饰符,限定哪个按键会触发事件 > 为了在必要的情况下支持旧浏览器,Vue 提供了绝大多数常用的按键码的别名 > .enter > > .tab > > .delete` (捕获“删除”和“退格”键)` > > .esc > > .space > > .up > > .down > > .left > > .right ~~~html
~~~ ## 修饰符别名 除了以上vue提供按钮的别名之外,我们还可以根据键盘为按键自定义别名 你还可以通过全局 `config.keyCodes` 对象[自定义按键修饰符别名](https://cn.vuejs.org/v2/api/#keyCodes): ~~~html Document
~~~ ## 系统修饰符 > 组合键 > > - `.ctrl` > - `.alt` > - `.shift` > - `.meta` windows键 ~~~html Document
~~~ # 表单输入绑定 > 表单输入绑定,即双向绑定:就是能够将vue实例的data数据渲染到表单输入视图(input\textarea\select),也能够将输入视图的数据同步更新到vue实例的data中 ~~~html Document
{{msg}}


Picked: {{ picked }}


Checked names: {{ checkedNames }}

{{city}}
~~~ # 组件介绍和使用 > 组件介绍及示例 > > 组件,就是将通用的HTML模块进行封装——可复用 ## 自定义组件的结构 > - `data` 定义组件的模板渲染的数据 > - `template` 组件的HTML模块(HTML标签\css样式) > - `methods` 定义组件中的标签事件绑定的JS函数 ## 全局组件注册 ~~~html Document
~~~ ## 私有组件 ~~~html Document
~~~ ## 切换组件 > Vue提供了component来展示对应名称的组件 component是一个占位符 :is属性用来指定要显示的组件的名称 ~~~html Document ~~~ ## 组件通信 > vue实例本身就是一个组件(模板就是el指定容器 ,data就是组件数据,methods就是组件的事件函数) > 在vue实例指定的el容器中引用的组件称为子组件 ,当前vue实例就是父组件 ### 父传子 > vue实例引用组件的时候,传递数据到引用的组件中,示意图 > ![](imgs/vue/1618977261480.png) > 代码示例父中代码 > > ~~~html > > > > > > > Document > > >
> >
> > > > > > > ~~~ > 子组件示例 > > **props:["title"]** > > ~~~html > const Feature = Vue.component('header-bar',{ > data:function(){ > return { > //title:"亲爱的小管" > } > }, > template:`
> > > > > > >
> > > > > >
>
`, > props:["title"], > methods:{ > test:function(){ > alert("组件中定义的函数") > } > } > } > ); > ~~~ ### 子传父 > 通过子组件的按钮“调用”父组件的函数,通过函数传值.示意图 > > ![](imgs/vue/1618978096426.png) ~~~html Document
从子组件传递过来的数据{{str1}} - {{str2}}
~~~ ## 组件插槽 > 当我们自定义vue组件时,允许组件中的部分内容在调用组件时进行定义——插槽 > 1. 插槽的使用 > > 在自定义组件时通过`slot`标签在组件的模版中定义插槽 > > ~~~html > > > > > > > Document > > > >
> > > >
> > > > > > ~~~ > 2. 具名插槽 > > 当组件中的插槽数量>1时,需要给组件中的slot标签添加name属性指定插槽的名字 > > ~~~html > > > > > > > Document > > > >
> > > > >
> > > > > > ~~~ > 3. 插槽作用域 > > 定义组件时,将组件中的数据绑定到`slot`标签 > > ~~~html > > > > > > > Document > > > >
> > > > > >
> > > > > > ~~~ # axios > vue可以实现数据的渲染,但是如何获取数据呢? > > vue本身不具备通信能力,通常结合axios—一个专注于异步通信的js框架来使用 > > - axios 数据通信 > - vue 数据渲染 ## axios入门 > - 原生ajax --- 实现步骤复杂 > - jQuery 笨重 > - axios 简洁、高效,对RESTful支持良好 ## 案例 > 1. get请求 - 查询所有 > > ~~~html > > > > > > > Document > > >
> > > >
> > > > > > ~~~ > > 后端 > > ~~~java > @CrossOrigin > @Api(value = "axios",tags = "axios交互接口") > @RestController > @RequestMapping("/axios") > public class AxiosController { > @ApiOperation("查询所有") > @GetMapping > public ResultVO hello(){ > Users users = new Users(); > users.setNickname("梦中人"); > users.setRealname("亲爱的小管"); > users.setUserBirth(new Date()); > return new ResultVO(200,"get请求",users); > > } > } > ~~~ > 2. get请求传参- 使用params > > ~~~html > > > > > > > Document > > >
> > > > >
> > > > > > ~~~ > > 后端 > > ~~~java > @ApiOperation("传参") > @GetMapping > public ResultVO hello2(String name,Integer id){ > Users users = new Users(); > users.setNickname(name); > users.setUserId(id); > users.setUserBirth(new Date()); > > return new ResultVO(200,"get请求接受参数",users); > } > ~~~ > 3. get请求传参-字符串拼接形式 > > ~~~html > > > > > > > Document > > >
> > > > >
> > > > > > ~~~ > > 后端 > > ~~~java > @ApiOperation("传参") > @GetMapping > public ResultVO hello2(String name,Integer id){ > Users users = new Users(); > users.setNickname(name); > users.setUserId(id); > users.setUserBirth(new Date()); > > return new ResultVO(200,"get请求接受参数",users); > } > ~~~ > > 4. get请求传参restful > > ~~~js > search2:function(name,id){ > axios.get('http://localhost:8888/axios/'+name+'/'+id).then(function(res){ > console.log(res.data.data) > vm.user = res.data.data > > }) > } > ~~~ > > ~~~java > @ApiOperation("传参") > @GetMapping("/{name}/{id}") > public ResultVO hello2(@PathVariable("name") String name, @PathVariable("id") Integer id){ > Users users = new Users(); > users.setNickname(name); > users.setUserId(id); > users.setUserBirth(new Date()); > > return new ResultVO(200,"get请求接受参数restful",users); > > ~~~ > 5. post请求 > > ~~~js > search3:function(name,id){ > axios.post('http://localhost:8888/axios/'+name+'/'+id).then(function(res){ > console.log(res.data.data) > vm.user = res.data.data > }) > } > ~~~ > > 或者 > > ~~~js > search3:function(name,id){ > axios.post('http://localhost:8888/axios?name='+name+'&id='+id).then(function(res){ > console.log(res.data.data) > vm.user = res.data.data > }) > } > 6. post请求注意点 > > 如果前端发送参数是这样写的 > > ~~~js > search3:function(name,id){ > axios.post('http://localhost:8888/axios',{ > username:name, > userId:id > > }).then(function(res){ > console.log(res.data.data) > vm.user = res.data.data > > }) > } > ~~~ > > 那么后端接受数据的时候需要配合使用@RequestBody > > ~~~java > @ApiOperation("传参") > @PostMapping > public ResultVO hello3(@RequestBody Users users){ > System.out.println(users); > > return new ResultVO(200,"get请求接受参数",users); > } > ~~~ > > 7. delete请求 > > ~~~js > axios.delete('http://localhost:8888/axios',{ > params:{ > username:name, > userId:id > } > 或者 > search4:function(name,id){ > axios.delete('http://localhost:8888/axios/'+name+'/'+id) > .then(function(res){ > console.log(res.data.data) > vm.user = res.data.data > > }) > } > 或者使用字符串拼接 > ~~~ ## 执行多个并发请求 ~~~js function getUserAccount() { return axios.get('/user/12345'); } function getUserPermissions() { return axios.get('/user/12345/permissions'); } axios.all([getUserAccount(), getUserPermissions()]) .then(axios.spread(function (acct, perms) { // 两个请求现在都执行完成 })); ~~~ ## 箭头函数 ~~~js //箭头函数 search4:function(name,id){ axios.delete('http://localhost:8888/axios/'+name+'/'+id) .then(res=>{ console.log(res); vm.user = res.data.data }) } ~~~ # 路由router > 单页面应用中使用场景居多 > > router是由vue官方提供的用于实现组件跳转的插件 ## 下载 > 路由插件的引用 **离线使用** ```html ``` **在线CDN** ```html ``` #### ## 入门案例 ~~~html Document
登录 注册

~~~ ## 动态路由匹配 > 通配符*可以匹配任意路径 例如: - `/user-*` 匹配所有以`user-`开头的任意路径 - `/*` 匹配所有路径 `注意`如果使用通配符定义路径,需要注意路由声明的顺序 示例如下: ~~~html Document
登录 注册

~~~ ## 路由传参 > `/a/:id` 可以匹配 `/a/`开头的路径 > > {{$route.params.id}}用于获取参数 示例如下 ~~~html Document
删除
~~~ > `通过props传参` ~~~html
路径A
~~~ ## 嵌套路由 > 在一级路由的组件中显示二级路由 示例如下: ~~~html Document
首页 首页-c1 首页-c2
~~~ ## 编程式导航 ### hello示例 ~~~html Document
~~~ ### push参数 > 1. 字符串 > > myrouter.push("/a"); > > 2. 对象 > > myrouter.push({path:"/a"}) > > 3. 命名路由 > > > ~~~js > > // myrouter.push({ > > // name:"r1", > > // params:{id:100} > > // }) > > ~~~ > > > > ~~~js > > const myrouter = new VueRouter({ > > routes:[ > > { > > path:"/a/:id", > > name:"r1", > > component:t1 > > } > > ] > > }); > > ~~~ > > > > 给路由取个名字 - 路由的命名 > > > > params传参 - 接受参数如下 > > > > ~~~js > > const t1 = {template:`
index=>{{$route.params.id}}
`} > > ~~~ > 4. url传参 相当于/a?id=101 > > ~~~js > // myrouter.push({ > // name:"r1", > // query:{ > // id:101 > // } > // }) > ~~~ > > query传参,接受参数如下 > > ~~~js > const t1 = {template:`
index=>{{$route.query.id}}
`} > ~~~ > 5. restful传参 相当于/a/100 > > ~~~js > myrouter.push({ > path:"/a/200" > }) > ~~~ > > ~~~js > routes:[ > { > path:"/a/:id", > name:"r1", > component:t1 > } > ] > ~~~ > > restful接受参数如下 > > ~~~js > const t1 = {template:`
index=>{{$route.params.id}}
`} > ~~~ 示例代码如下: ~~~html Document
~~~ ### replace() ~~~js 功能与push一致,区别在于replace()不会向history添加新的浏览记录 ~~~ ### go() > 参数为一个整数,表示在浏览器历史记录中前后/后退多少步 相当于`window.history.go(-1)`的作用 ## 命名路由 > 命名路由:在定义路由的时候可以给路由指定name,我们在进行路由导航时可以通过路由的名字导航 示例如下 ~~~html Document

login register
~~~ ## 命名路由视图 > 如果在HTML中有一个以上的路由视图router-view,需要给router-view指定name,在路由中使用components映射多个组件根据name设置组件与router-view绑定关系 示例如下 ~~~html Document
t1 t2
~~~ ## 重定向和别名 > 1. 根据路由路径重定向 > 2. 根据路由name重定向 > 3. 根据路由别名重定向 > 演示重定向 > 访问`/b`,重定向到`/a` ~~~html Document
路径A 路径B
~~~ > 根据路由命名重定向 ~~~js routes:[ { path:"/a", name:"r1", component:t1 }, { path:"/b", //根据路径重定向 //redirect:"/a" //根据路由命名重定向 redirect:{name:"r1"} } ] ~~~ > 根据路由别名重定向 ~~~html Document
路径A 路径B 路由别名
~~~ # ElementUI > 官网-https://element.eleme.io/#/zh-CN CDN在线引入 > ~~~css > > > > > ~~~ 离线方式 - 下载上述俩个文件,在html文件中引入即可