前后端分离-小项目-3前后端交互

第一步编写前端页面,第二步搭建后端环境,现在开始第三步,继续完善前端功能


完善“添加”按钮功能

  1. Ajax异步请求安装

  • 在前端项目安装ajax。在Terminal输入:npm i axios -S

  1. 点击“添加”按钮,弹出Dialog对话框

  1. 设置对话框里面的内容——表单

  • 对话框选用Dialog

  • 嵌入表单menu,二者一起构成了新增对话框

  • 注意v-model,:model,变量,方法的设置及格式

    
    
      
      
        
          
        
        
          
        
        
          
        
        
          
        
        
          
        
      
      
    
  1. 创建axios request

  • 命名成了myRequest,便于区别request

// 引入axios
import axios from 'axios';
// 通过axios创建对象-request,用于发送请求到后端
const myRequest=axios.create({
    timeout: 5000
})
// request拦截器处理
myRequest.interceptors.request.use(config=>{
    config.headers['Content-Type']='application/json;charset=utf-8'
    return config
},error => {
    return Promise.reject(error)
})
export default myRequest
  1. 跨域异常:AxiosError/跨源

  • 修改vue.config.js

module.exports = {
    devServer: {
        port: 10000,
        proxy:{ //设置代理,必填
            "/api":{    //设置拦截器,格式:/+名字
                target:"http://localhost:8080" ,//目标地址,就是'/api'要替换的地址
                changeOrigin:true,              //设置是否同源,设为是。实现跨域
                pathRewrite:{                   //路径重写
                    '/api':''                   //选择忽略拦截器里面的单词
                }
            }
        }
    }
}
  • HomeView.vue修改ajax的访问url:"localhost:8080/save"改为。前后端即可通信

myRequest.post("/api/save",this.furn).then(

显示所有家居信息

思路分析

  1. 完成后台代码从mapper->service->controller,并使用Postman对代码进行测试

  • 因为使用搭建的环境,mybatis-plus已经完成了mapper\service层,直接完成controller即可

    @RequestMapping("/list")
    public Result listFurns(){
        List furns = furnService.list();
        return Result.success(furns);
    }
  1. 完成前台代码,使用axios发送http请求,返回所有家居数据,将数据绑定显示

  methods:{
    list(){
      myRequest.get("/api/list").then(res=>{
        console.log("res=",res);
        this.tableData=res.data.data;
      })
    },
  1. 调用显示数据的方法。VUE生命周期

  created(){
    this.list()
  },
  1. 增加 处理响应后的结果

  • 主要是练习这种处理方式。这儿的用处不大

  • 实际产生的作用就是把response.data的数据层级拿出来了一层,达成下面这个效果

  • this.tableData=res.data.data=>this.tableData=res.data;前端HomeView.vue

// response拦截器,返回结果处理
myRequest.interceptors.response.use(response=>{
    let res=response.data
    if(response.config.responseType==='blob'){
        return res;
    }
    if(typeof res==='string'){
        res=res? JSON.parse(res):res
    }
    return res;
})
  1. 在save()方法增加list(),完成刷新

  • 之前在list()方法里面加入了list(),导致循环,致使view页面不能显示

  • list()方法加在res=>{}括号里面,在页面能立马看到更新效果。原因是Ajax的异步机制

  • Ajax有通讯,运行慢,=>{}而括号外的代码在本机执行快,就导致list更新在新数据到来之前就执行了,导致看不到更新效果。

    save(){
      ...
      this.list() //新增
    },

回显家具信息,并完成修改

思路分析

  1. 完成后台代码从mapper->service->controller,并对代码进行测试

  • 破案了。updateById()这个方法来自于接口IService,它是谁实现的呢?它自己!接口的默认实现

    @PutMapping("/update")
    public Result updateFurn(@RequestBody Furn furn){
        log.info("待修改的furn="+furn);
        furnService.updateById(furn);
        return Result.success();
    }
  1. 完成前台代码,回显家居信息[方式1:直接将点击的表格当前行的数据进行回显,方式2(先思考,尝试完成):根据当前行的id(家居id),到db查询对应的数据,进行回显],再使用axios发送http请求,更新数据,将数据绑定显示

  • 获取当前行数据的方法,就是在该行@Click=handleEdit(scope.row),在方法区,使用该方法,带入参数(row)即可获取。插槽机制

  • row对象转换成JSON格式的过程

  • JSON.parse(JS0N.stringify(row))就是对行数据进行深拷贝

  • 这样点击的表格当前行的数据和弹出框的数据是独立的

    handleEdit(row){
      // 输出原始row
      console.log("row1=",row)
      // 字符串化row
      console.log("row2=",JSON.stringify(row))
      // JSON格式row
      console.log("row3=",JSON.parse(JSON.stringify(row)))
    },
  • 回显当前行数据。方式1:

  methods:{
    handleEdit(row){
      this.form= JSON.parse(JSON.stringify(row))    //获取当前行数据。并放到表单
      this.dialogVisible=true         //显示表单
    },
  • 从后端拿到数据再回显。方式2:

  • 修改当前行数据,以及成功状态返回。同样也存在Ajax异步,更新list()要放在then()里面

save(){
      if(this.form.id){//此时执行更新
        myRequest.put("/api/update",this.form).then(
            res=>{
              if(res.code==="200"){//更新成功
                this.$message({
                  type: "success",
                  message: res.msg
                })
              }else{//更新失败
                this.$message({
                  type:"error",
                  message:"更新数据失败"
                })
              }

              this.dialogVisible = false
              this.list()
            })
      }else{//此时执行添加
        myRequest.post("/api/save",this.form).then(
            res=>{
              // res就是后端输出给前端的结果
              console.log("res",res)
              this.dialogVisible = false
              this.list()
            })
      }
    },

删除家居项

思路分析

  1. 完成后台代码从mapper->service->controller,并对代码进行测试

    @DeleteMapping("/del/{id}")
    public Result deleteFurn(@PathVariable Integer id){
        furnService.removeById(id);
        return Result.success();
    }
  1. 完成前台代码,使用axios发送http请求,删除数据,将数据绑定显示

  • 注意删除的方法是用@confirm在绑定的,而不是在用@click。

        
  • handleDel()方法的具体实现

  • 完成后用list()进行刷新。同样注意位置,避免ajax异步导致刷新异常。

    handleDel(row){
      myRequest.delete("/api/del/"+row.id).then(res=>{
        if(res.code==="200"){
          this.$message({
            type:"success",
            message:res.msg
          })
        }else{
          this.$message({
            type:"error",
            message:res.msg
          })
        }
        this.list()
      })
    }

分页功能

需求分析

1.显示共多少记录

2.可以设置每项显示几条

3.点击第几页,显示对应数据

思路分析

1.后台使用MyBatis-plus分页插件完成查询

2.修改FurnController,增加处理分页显示代码

3.完成前台代码,加入分页导航,并将分页请求和后台接口结合


  1. 创建config/MybatisplusConfig.java配置类。配置分页插件


@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        //需要注入的对象
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //添加分页插件
        //设置数据库类型
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}
  1. 增加分页插件的调用处理

  • application.yml配置输出日志。便于调试

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  • 完成后端分页功能

    @RequestMapping("/page")
    public Result page(@RequestParam(defaultValue = "1") Integer pageNum,
                       @RequestParam(defaultValue = "5") Integer pageSize){
        Page furnPage = furnService.page(new Page<>(pageNum, pageSize));
        return Result.success(furnPage);
    }
  1. 增加前端分页控件,并在数据池完善参数。

    
  1. 完成控件功能

  • 完善分页长度,显示指定页码内容的方法。注意方法参数名是自定义的,由控件传入

  methods:{
    handleSizeChange(pageSize){
      this.pageSize=pageSize
      this.list()
    },

    handleCurrentChange(currentPage){
      this.currentPage=currentPage
      this.list()
    },
  • 采用分页方法显示,重写显示列表

  • 注意url添加参数的格式。而且参数名需要和后端接收参数名一致。

  • 注意返回接收数据时,表数据和总条数分别来自于records和total。记不得可以利用console的输出,自己手动查询变量名称后完善。

list(){
      // 采用分页方式更新数据列表
      myRequest.get("/api/page",{
        params:{
          pageNum:this.currentPage,
          pageSize:this.pageSize
        }
      }).then(res=>{
        console.log("res=",res)
        this.tableData=res.data.records
        this.totalCount=res.data.total
      })
    },

切换数据源为DruidDataSource

  • 检查在pom.xml是否已经配置

        
            com.alibaba
            druid
            1.1.17
        
  • 创建配置类,完成注入

@Configuration
@Slf4j
public class DruidDataSourceConfig {
    @Bean
    @ConfigurationProperties("spring.datasource")
    public DataSource dataSource(){
        DruidDataSource druidDataSource = new DruidDataSource();
        log.info("数据源={}",druidDataSource.getClass());
        return druidDataSource;
    }
}
  • 注意@ConfigurationProperties("spring.datasource")是已经配置在application.yml的

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/furn_ssm?useSSL=true&useUnicode=true&charactorEncoding=utf-8
    password: root
    username: root
    driver-class-name: com.mysql.cj.jdbc.Driver

带条件检索的分页显示

思路分析

  1. 完成后台代码从mapper->service->controller,并对代码进行测试

  • 构造用的是Wrappers的静态方法,而不是new ...

  • 带条件的分页查找。page(分页,条件queryWrapper)

    @RequestMapping("/search")
    public Result pageBySearch(
            @RequestParam(defaultValue = "1")Integer pageNum,
            @RequestParam(defaultValue = "5")Integer pageSize,
            @RequestParam(defaultValue = "")String search
    ){
        QueryWrapper queryWrapper = Wrappers.query();
        if(StringUtils.hasText(search)){
            queryWrapper.like("name",search);
        }
        Page furnPage =
                furnService.page(new Page<>(pageNum, pageSize), queryWrapper);
        return Result.success(furnPage);
    }
  1. 完成前台代码,使用axios发送http请求,完成带条件查询分页显示

  • 前端按键添加响应方法

查询
  • 注意参数的增加

    list(){
      //改用带条件的分页查询
      myRequest.get("/api/search",{
        params:{
          pageNum:this.currentPage,
          pageSize:this.pageSize,
          search:this.search
        }
      }).then(res=>{...

你可能感兴趣的:(SpringBoot,前端,spring,boot,后端)