JavaWeb基础教程-----(12)VUE&Element&综合案例

1 VUE

1.1 Vue概述

  • Vue 是一套前端框架,免除原生JavaScript中的DOM操作,简化书写
  • 基于MVVM(Model-View-ViewModel)思想,实现数据的双向绑定,将编程的关注点放在数据上
  • 官网:https://cn.vuejs.org

MVVM与MVC:
在这里插入图片描述
在这里插入图片描述
MVVM:可以实现数据的双向绑定
MVVM可以实现模型和视图双向绑定:
双向绑定是指当模型发生变化时,视图的会随之发生变化;而如果视图发生变化,绑定的模型数据也随之发生变化。
双向绑定作用:
从界面的操作能实时反映到数据,数据的变更能实时展现到界面

1.2 Vue快速入门

  1. 新建 HTML 页面,引入 Vue.js文件,下载Vue,js文件教程
    在这里插入图片描述

  2. 在JS代码区域,创建Vue核心对象,传入JSON对象进行数据绑定
    在这里插入图片描述

  3. 编写视图
    在这里插入图片描述

【示例】Vue快速入门

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <input v-model="username">
    <!--插值表达式-->
    {{username}}
</div>

<script src="js/vue.js"></script>

<script>

  //1.创建vue的核心对象
  new Vue({
      el:"#app",
      data(){
          return {
              username:""
          }
      }
  });


</script>

</body>
</html>

浏览器显示:
在这里插入图片描述

1.3 Vue的常用指令

  • 指令:HTML 标签上带有 v- 前缀的特殊属性,不同指令具有不同含义。例如:v-if,v-for…
  • 常用指令:
    在这里插入图片描述
  1. v-bind:为HTML标签绑定属性值,如设置 href , css样式等
    在这里插入图片描述
  2. v-model:在表单元素上创建双向数据绑定
    在这里插入图片描述
  3. v-on:为HTML标签绑定事件
    • html:
      在这里插入图片描述
    • vue:
      在这里插入图片描述
  4. v-if和v-show:
    在这里插入图片描述
    • v-if:
      在这里插入图片描述
    • v-show:
      在这里插入图片描述
  5. v-for:列表渲染,遍历容器的元素或者对象的属性
    在这里插入图片描述

1.4 Vue生命周期

  • 生命周期的八个阶段:每触发一个生命周期事件,会自动执行一个生命周期方法,这些生命周期方法也被称为钩子方法
    在这里插入图片描述

  • Vue 官网提供的从创建 Vue 到效果 Vue 对象的整个过程及各个阶段对应的钩子函数:
    在这里插入图片描述

  • mounted:挂载完成,Vue初始化成功,HTML页面渲染成功。而以后我们会在该方法中发送异步请求,加载数据。

  • 示例
    在这里插入图片描述

1.5 案例

需求:使用Vue简化品牌列表数据查询和添加功能

1.5.1 查询所有

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <a href="addBrand.html"><input type="button" value="新增"></a><br>
    <hr>
    <table id="brandTable" border="1" cellspacing="0" width="100%">
        <tr>
            <th>序号</th>
            <th>品牌名称</th>
            <th>企业名称</th>
            <th>排序</th>
            <th>品牌介绍</th>
            <th>状态</th>
            <th>操作</th>
        </tr>
        <!--
            使用v-for遍历tr
        -->
        <tr v-for="(brand,i) in brands">
            <td>{{i+1}}</td>
            <td>{{brand.brandName}}</td>
            <td>{{brand.companyName}}</td>
            <td>{{brand.ordered}}</td>
            <td>{{brand.description}}</td>
            <td v-if="brand.status==1">启用</td>
            <td v-else>禁用</td>
            <td><a href="#">修改</a> <a href="#">删除</a></td>
        </tr>
    </table>
</div>
<script src="js/axios-0.18.0.js"></script>
<script src="js/vue.js"></script>
 
<script>
    new Vue({
        el: "#app",
        data(){
            return{
                brands:[]
            }
        },
        mounted(){
            // 页面加载完成后,发送异步请求,查询数据
            var _this = this;
            axios({
                method:"get",
                url:"http://localhost:8080/brand-demo/selectAllServlet"
            }).then(function (resp) {
                _this.brands = resp.data;
            })
        }
    })
</script>
</body>
</html>

小tips:
在这里插入图片描述

1.5.2 新增品牌

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <title>添加品牌</title>
</head>
<body>
<div id="app">
    <h3>添加品牌</h3>
    <form action="" method="post">
        品牌名称:<input id="brandName" v-model="brand.brandName" name="brandName"><br>
        企业名称:<input id="companyName" v-model="brand.companyName" name="companyName"><br>
        排序:<input id="ordered" v-model="brand.ordered" name="ordered"><br>
        描述信息:<textarea rows="5" cols="20" id="description" v-model="brand.description" name="description"></textarea><br>
        状态:
        <input type="radio" name="status" v-model="brand.status" value="0">禁用
        <input type="radio" name="status" v-model="brand.status" value="1">启用<br>
 
        <input type="button" id="btn" @click="submitForm" value="提交">
    </form>
</div>
<script src="js/axios-0.18.0.js"></script>
<script src="js/vue.js"></script>
<script>
    new Vue({
        el: "#app",
        data(){
            return {
                brand:{}
            }
        },
        methods:{
            submitForm(){
                // 发送ajax请求,添加
                var _this = this;
                axios({
                    method:"post",
                    url:"http://localhost:8080/brand-demo/addServlet",
                    data:_this.brand
                }).then(function (resp) {
                    // 判断响应数据是否为 success
                    if(resp.data == "success"){
                        location.href = "http://localhost:8080/brand-demo/brand.html";
                    }
                })
            }
        }
    })
</script>
</body>
</html>

2 Element

2.1 Element概述

  • Element:是饿了么公司前端开发团队提供的一套基于 Vue 的网站组件库,用于快速构建网页
  • 组件:组成网页的部件,例如 超链接、按钮、图片、表格等等
  • Element官网

2.2 Element快速入门

  1. 引入Element的css、js文件和Vue.js
    在这里插入图片描述

  2. 创建Vue核心对象
    在这里插入图片描述

  3. 官网复制Element组件代码

【示例】Element快速入门

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
 
 
    <el-row>
     	<el-button>默认按钮</el-button>
        <el-button type="primary">主要按钮</el-button>
        <el-button type="success">成功按钮</el-button>
        <el-button type="info">信息按钮</el-button>
        <el-button type="warning">警告按钮</el-button>
        <el-button type="danger">删除</el-button>
    </el-row>
 
</div>
 
<script src="js/vue.js"></script>
<script src="element-ui/lib/index.js"></script>
<link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css">
 
<script>
    new Vue({
        el:"#app"
    })
</script>
 
</body>
</html>

2.3 Element布局

  • Element 提供了两种布局方式,分别是:
    Layout 布局:通过基础的24分栏,迅速简便的创建布局
    Container 布局容器:用于布局的容器组件,方便快速搭建页面的基本结构
  1. Layout布局:
    在这里插入图片描述
    在左菜单栏找到 Layout 布局 ,点击 显示代码 ,在下面就会展示出对应的代码,显示出的代码中有样式,有html标签。
    将样式<style>拷贝我们自己页面的 head 标签内,将html标签拷贝到<div id=“app”></div> 标签内。

  2. Container 布局容器
    在这里插入图片描述该效果代码中包含了样式、页面标签、模型数据。将里面的样式<style> 拷贝到我们自己页面的 head 标签中;将html标签拷贝到<div id=“app”></div> 标签中,再将数据模型拷贝到 vue 对象的 data() 中。

2.4 Element组件–brand案例

在这里插入图片描述

2.4.1 表格

首先拷贝Element 代码
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

  <style>
    .el-table .warning-row {
      background: oldlace;
    }

    .el-table .success-row {
      background: #f0f9eb;
    }
  </style>

</head>
<body>
<div id="app">

  <!--表格-->
  <template>
    <el-table
            :data="tableData"
            style="width: 100%"
            :row-class-name="tableRowClassName">
      <el-table-column
              prop="date"
              label="日期"
              width="180">
      </el-table-column>
      <el-table-column
              prop="name"
              label="姓名"
              width="180">
      </el-table-column>
      <el-table-column
              prop="address"
              label="地址">
      </el-table-column>
    </el-table>
  </template>
</div>

<script src="js/vue.js"></script>
<script src="js/element-ui/lib/index.js"></script>
<link rel="stylesheet" href="js/element-ui/lib/theme-chalk/index.css">

<script>
  new Vue({
    el:"#app",
    methods: {
      tableRowClassName({row, rowIndex}) {
        if (rowIndex === 1) {
          return 'warning-row';
        } else if (rowIndex === 3) {
          return 'success-row';
        }
        return '';
      }
    },
    data() {
      return {
        tableData: [{
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄',
        }, {
          date: '2016-05-04',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄'
        }, {
          date: '2016-05-01',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄',
        }, {
          date: '2016-05-03',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄'
        }]
      }
    }
  })

</script>

</body>
</html>

效果:
在这里插入图片描述
修改代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

  <style>
    .el-table .warning-row {
      background: oldlace;
    }

    .el-table .success-row {
      background: #f0f9eb;
    }
  </style>

</head>
<body>
<div id="app">

  <!--表格-->
  <template>
    <el-table
            :data="tableData"
            style="width: 100%"
            :row-class-name="tableRowClassName"
            @selection-change="handleSelectionChange">
      <el-table-column
              type="selection"
              width="55">
      </el-table-column>
      <el-table-column
              type="index"
              width="50">
      </el-table-column>
      <el-table-column
              prop="brandName"
              label="品牌名称"
              align="center"
              >
      </el-table-column>
      <el-table-column
              prop="companyName"
              label="企业名称"
              align="center"
              >
      </el-table-column>
      <el-table-column
              prop="ordered"
              label="排序"
              align="center">
      </el-table-column>
      <el-table-column
              prop="status"
              label="当前状态"
              align="center"
              >
      </el-table-column>
      <el-table-column
              label="操作"
              align="center">
      <el-row>
        <el-button type="primary" disabled>修改</el-button>
        <el-button type="danger" disabled>删除</el-button>
      </el-row>

      </el-table-column>
    </el-table>
  </template>
</div>

<script src="js/vue.js"></script>
<script src="js/element-ui/lib/index.js"></script>
<link rel="stylesheet" href="js/element-ui/lib/theme-chalk/index.css">

<script>
  new Vue({
    el:"#app",
    methods: {
      tableRowClassName({row, rowIndex}) {
        if (rowIndex === 1) {
          return 'warning-row';
        } else if (rowIndex === 3) {
          return 'success-row';
        }
        return '';
      },
      //复选框选中后执行的方法
      handleSelectionChange(val) {
        this.multipleSelection = val;
      }
    },
    data() {
      return {
        multipleSelection: [],
        
        tableData: [{
          brandName: '华为',
          companyName: '华为科技有限公司',
          ordered: '100',
          status:'1'
        }, {
          brandName: '华为',
          companyName: '华为科技有限公司',
          ordered: '100',
          status:'1'
        }, {
          brandName: '华为',
          companyName: '华为科技有限公司',
          ordered: '100',
          status:'1'
        }, {
          brandName: '华为',
          companyName: '华为科技有限公司',
          ordered: '100',
          status:'1'
        }]
      }
    }
  })

</script>

</body>
</html>

效果:
在这里插入图片描述

2.4.2 表单

在这里插入图片描述
复制和修改代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

  <style>
    .el-table .warning-row {
      background: oldlace;
    }

    .el-table .success-row {
      background: #f0f9eb;
    }
  </style>

</head>
<body>
<div id="app">

  <!--表单-->
  <el-form :inline="true" :model="brand" class="demo-form-inline">
    <el-form-item label="当前状态">
      <el-select v-model="brand.status" placeholder="当前状态">
        <el-option label="启用" value="1"></el-option>
        <el-option label="禁用" value="0"></el-option>
      </el-select>
    </el-form-item>
    <el-form-item label="企业名称">
      <el-input v-model="brand.companyName" placeholder="企业名称"></el-input>
    </el-form-item>
    <el-form-item label="品牌名称">
      <el-input v-model="brand.brandName" placeholder="品牌名称"></el-input>
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="onSubmit">查询</el-button>
    </el-form-item>
  </el-form>

  <!--表格-->
  <template>
    <el-table
            :data="tableData"
            style="width: 100%"
            :row-class-name="tableRowClassName"
            @selection-change="handleSelectionChange">
      <el-table-column
              type="selection"
              width="55">
      </el-table-column>
      <el-table-column
              type="index"
              width="50">
      </el-table-column>
      <el-table-column
              prop="brandName"
              label="品牌名称"
              align="center"
              >
      </el-table-column>
      <el-table-column
              prop="companyName"
              label="企业名称"
              align="center"
              >
      </el-table-column>
      <el-table-column
              prop="ordered"
              label="排序"
              align="center">
      </el-table-column>
      <el-table-column
              prop="status"
              label="当前状态"
              align="center"
              >
      </el-table-column>
      <el-table-column
              label="操作"
              align="center">
      <el-row>
        <el-button type="primary" disabled>修改</el-button>
        <el-button type="danger" disabled>删除</el-button>
      </el-row>

      </el-table-column>
    </el-table>
  </template>
</div>

<script src="js/vue.js"></script>
<script src="js/element-ui/lib/index.js"></script>
<link rel="stylesheet" href="js/element-ui/lib/theme-chalk/index.css">

<script>
  new Vue({
    el:"#app",
    methods: {
      tableRowClassName({row, rowIndex}) {
        if (rowIndex === 1) {
          return 'warning-row';
        } else if (rowIndex === 3) {
          return 'success-row';
        }
        return '';
      },
      //复选框选中后执行的方法
      handleSelectionChange(val) {
        this.multipleSelection = val;
      },

      //查询方法
      onSubmit() {
        console.log('submit!');
      }
    },
    data() {
      return {
        //搜索表单数据
        brand: {
          status: '',
          brandName: '',
          companyName:''
        },

        //复选框选中数据集合
        multipleSelection: [],

        //表格数据
        tableData: [{
          brandName: '华为',
          companyName: '华为科技有限公司',
          ordered: '100',
          status:'1'
        }, {
          brandName: '华为',
          companyName: '华为科技有限公司',
          ordered: '100',
          status:'1'
        }, {
          brandName: '华为',
          companyName: '华为科技有限公司',
          ordered: '100',
          status:'1'
        }, {
          brandName: '华为',
          companyName: '华为科技有限公司',
          ordered: '100',
          status:'1'
        }]
      }
    }
  })

</script>

</body>
</html>

效果:
在这里插入图片描述

2.4.3 对话框和表单

在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

【示例】复制和修改后的代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

  <style>
    .el-table .warning-row {
      background: oldlace;
    }

    .el-table .success-row {
      background: #f0f9eb;
    }
  </style>

</head>
<body>
<div id="app">

  <!--表单-->
  <el-form :inline="true" :model="brand" class="demo-form-inline">
    <el-form-item label="当前状态">
      <el-select v-model="brand.status" placeholder="当前状态">
        <el-option label="启用" value="1"></el-option>
        <el-option label="禁用" value="0"></el-option>
      </el-select>
    </el-form-item>
    <el-form-item label="企业名称">
      <el-input v-model="brand.companyName" placeholder="企业名称"></el-input>
    </el-form-item>
    <el-form-item label="品牌名称">
      <el-input v-model="brand.brandName" placeholder="品牌名称"></el-input>
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="onSubmit">查询</el-button>
    </el-form-item>
  </el-form>

  <!--按钮-->
  <el-row>
    <el-button type="danger" plain>批量删除</el-button>
    <el-button type="primary" plain @click="dialogVisible = true">新增</el-button>
  </el-row>

  <!--添加数据对话框表单-->
  <el-dialog
          title="编辑品牌"
          :visible.sync="dialogVisible"
          width="30%">

    <el-form ref="form" :model="form" label-width="80px">
      <el-form-item label="品牌名称">
        <el-input v-model="brand.brandName"></el-input>
      </el-form-item>
      <el-form-item label="企业名称">
        <el-input v-model="brand.companyName"></el-input>
      </el-form-item>
      <el-form-item label="排序">
        <el-input v-model="brand.ordered"></el-input>
      </el-form-item>
      <el-form-item label="备注">
        <el-input type="textarea" v-model="brand.description"></el-input>
      </el-form-item>
      <el-form-item label="状态">
        <el-switch v-model="brand.status"
                   active-value="1"
                   inactive-value="0"></el-switch>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="addBrand">提交</el-button>
        <el-button @click="dialogVisible = false">取消</el-button>
      </el-form-item>
    </el-form>

  </el-dialog>

  <!--表格-->
  <template>
    <el-table
            :data="tableData"
            style="width: 100%"
            :row-class-name="tableRowClassName"
            @selection-change="handleSelectionChange">
      <el-table-column
              type="selection"
              width="55">
      </el-table-column>
      <el-table-column
              type="index"
              width="50">
      </el-table-column>
      <el-table-column
              prop="brandName"
              label="品牌名称"
              align="center"
              >
      </el-table-column>
      <el-table-column
              prop="companyName"
              label="企业名称"
              align="center"
              >
      </el-table-column>
      <el-table-column
              prop="ordered"
              label="排序"
              align="center">
      </el-table-column>
      <el-table-column
              prop="status"
              label="当前状态"
              align="center"
              >
      </el-table-column>
      <el-table-column
              label="操作"
              align="center">
      <el-row>
        <el-button type="primary" disabled>修改</el-button>
        <el-button type="danger" disabled>删除</el-button>
      </el-row>

      </el-table-column>
    </el-table>
  </template>
</div>

<script src="js/vue.js"></script>
<script src="js/element-ui/lib/index.js"></script>
<link rel="stylesheet" href="js/element-ui/lib/theme-chalk/index.css">

<script>
  new Vue({
    el:"#app",
    methods: {
      tableRowClassName({row, rowIndex}) {
        if (rowIndex === 1) {
          return 'warning-row';
        } else if (rowIndex === 3) {
          return 'success-row';
        }
        return '';
      },
      //复选框选中后执行的方法
      handleSelectionChange(val) {
        this.multipleSelection = val;
      },

      //查询方法
      onSubmit() {
        console.log('submit!');
      },

      //添加数据
      addBrand(){

      }
    },
    data() {
      return {

        //添加数据对话框是否展示的标记
        dialogVisible: false,

        //品牌模型数据
        brand: {
          status: '',
          brandName: '',
          companyName:'',
          id:'',
          ordered:'',
          description:''
        },

        //复选框选中数据集合
        multipleSelection: [],

        //表格数据
        tableData: [{
          brandName: '华为',
          companyName: '华为科技有限公司',
          ordered: '100',
          status:'1'
        }, {
          brandName: '华为',
          companyName: '华为科技有限公司',
          ordered: '100',
          status:'1'
        }, {
          brandName: '华为',
          companyName: '华为科技有限公司',
          ordered: '100',
          status:'1'
        }, {
          brandName: '华为',
          companyName: '华为科技有限公司',
          ordered: '100',
          status:'1'
        }]
      }
    }
  })

</script>

</body>
</html>

2.4.4 分页工具条

在这里插入图片描述
【示例】复制和修改代码
在这里插入图片描述在这里插入图片描述

3 综合案例----商品列表展示以及增删改查

  • 功能:查询所有,新增品牌,修改品牌,删除品牌;批量删除,分页查询,条件查询

3.1 环境搭建

  1. 项目目录结构
    在这里插入图片描述导入依赖时出现的问题
  2. tb_brand.sql脚本
-- 删除tb_brand表
drop table if exists tb_brand;
-- 创建tb_brand表
create table tb_brand (
    -- id 主键
    id           int primary key auto_increment,
    -- 品牌名称
    brand_name   varchar(20),
    -- 企业名称
    company_name varchar(20),
    -- 排序字段
    ordered      int,
    -- 描述信息
    description  varchar(100),
    -- 状态:0:禁用  1:启用
    status       int
);
-- 添加数据
insert into tb_brand (brand_name, company_name, ordered, description, status)
values 
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
       ('华为', '华为技术有限公司', 100, '万物互联', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1),
       ('格力', '格力电器股份有限公司', 30, '让世界爱上中国造', 1),
       ('阿里巴巴', '阿里巴巴集团控股有限公司', 10, '买买买', 1),
       ('腾讯', '腾讯计算机系统有限公司', 50, '玩玩玩', 0),
       ('百度', '百度在线网络技术公司', 5, '搜搜搜', 0),
       ('京东', '北京京东世纪贸易有限公司', 40, '就是快', 1);
SELECT * FROM tb_brand;

3.2 查询所有

流程:
在这里插入图片描述实现:
Dao层:
在BrandMapper 接口中定义抽象方法,并使用 @Select 注解编写 sql 语句,由于表中有些字段名和实体类中的属性名没有对应,所以需要在BrandMapper.xml 映射配置文件中定义结果映射 ,使用resultMap 标签。定义完结果映射关系后,在接口 selectAll() 方法上引用该结构映射。使用 @ResultMap(“brandResultMap”) 注解

BrandMapper 接口:

public interface BrandMapper {

    /**
     * 查询所有
     * @return
     */
    @Select("select * from tb_brand")
    @ResultMap("brandResultMap")
    List<Brand> selectAll();
}

BrandMapper.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">
<mapper namespace="com.zs.mapper.BrandMapper">

    <resultMap id="brandResultMap" type="brand">
        <result column="brand_name" property="brandName"></result>
        <result column="company_name" property="companyName"></result>
    </resultMap>
</mapper>

service层:
在service 包下创建 BrandService 接口,在该接口中定义查询所有的抽象方法,并在service包 下再创建 impl 包;impl 表示是放 service 层接口的实现类的包。
BrandService 接口:

public interface BrandService {
 
    /**
     * 查询所有
     * @return
     */
    List<Brand> selectAll();
}

BrandServiceImpl 类代码如下:

public class BrandServiceImpl implements BrandService {

    //1.创建SqlSessionFactory工厂对象
    SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();
            
    @Override
    public List<Brand> selectAll() {
        //2.获取SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //3.获取BrandMapper
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
        //4.调用方法
        List<Brand> brands = brandMapper.selectAll();
        //5.释放资源
        sqlSession.close();

        return brands;
    }
}

定义service 接口的好处
因为service定义了接口后,在 servlet 中就可以使用多态的形式创建Service实现类的对象,如下:
在这里插入图片描述
这里使用多态是因为方便我们后期解除 Servlet 和 service 的耦合。
从上面的代码我们可以看到 SelectAllServlet 类和 BrandServiceImpl 类之间是耦合在一起的,如果后期 BrandService 有其它更好的实现类(例如叫 BrandServiceImpl),那就需要修改 SelectAllServlet 类中的service引用和实例化名代码,而使用多态形式就只需要修改实例化,引用和引用调用的方法、属性就不用更改。
后面我们学习了 Spring 框架后就可以解除 SelectAllServlet 类和红色框括起来的代码耦合。而现在咱们还做不到解除耦合,在这里只需要理解为什么定义接口即可。

Web层:
在 servlet 包下定义名为 SelectAllServlet 的查询所有的 servlet。
该 servlet 逻辑如下:
调用service的 selectAll() 方法查询所有的品牌数据,并接口返回结果
将返回的结果转换为 json 数据
响应 json 数据
SelectAllServlet:

package com.zs.web.servlet;

import com.alibaba.fastjson.JSON;
import com.zs.pojo.Brand;
import com.zs.service.BrandService;
import com.zs.service.impl.BrandServiceImpl;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.List;

@WebServlet("/selectAllServlet")
public class SelectAllServlet extends HttpServlet {
    private BrandService brandService = new BrandServiceImpl();
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.调用service查询
        List<Brand> brands = brandService.selectAll();
        //2.转为JSON
        String jsonString = JSON.toJSONString(brands);
        //3.写数据
        response.setContentType("text/json;charset=utf-8");
        response.getWriter().write(jsonString);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

运行,访问http://localhost:8080/brand-case/selectAllServlet:
在这里插入图片描述
编写中出现的问题

前端:

在这里插入图片描述运行,访问http://localhost:8080/brand-case/brand.html:
在这里插入图片描述

3.3 新增品牌

整体流程:
在这里插入图片描述实现:
Dao层:
在 BrandMapper 接口中定义 add() 添加方法,并使用 @Insert 注解编写sql语句
BrandMapper:

    /**
     * 添加
     * @param brand
     */
    @Insert("insert into tb_brand values(null,#{brandName},#{companyName},#{ordered},#{description},#{status})")
    void add(Brand brand);

Service层:
在 BrandService 接口中定义 add() 添加数据的业务逻辑方法,在 BrandServiceImpl 类中重写 add() 方法,并进行业务逻辑实现。
BrandService:

    /**
     * 添加数据
     * @param brand
     */
    void add(Brand brand);

BrandServiceImpl:

    @Override
    public void add(Brand brand) {
        //2.获取SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //3.获取BrandMapper
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
        //4.调用方法
        brandMapper.add(brand);
        sqlSession.commit();
        //5.释放资源
        sqlSession.close();
    }

Web层:
定义名为 AddServlet 的 Servlet。
该 Servlet 的逻辑如下:
接收页面提交的数据。页面到时候提交的数据是 json 格式的数据,所以此处需要使用输入流读取数据
将接收到的数据转换为 Brand 对象
调用 service 的 add() 方法进行添加的业务逻辑处理
给浏览器响应添加成功的标识,这里直接给浏览器响应 success 字符串表示成功
AddServlet:

@WebServlet("/addServlet")
public class AddServlet extends HttpServlet {
    private BrandService brandService = new BrandServiceImpl();
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 接收品牌的数据
        BufferedReader br = request.getReader();
        String params = br.readLine();  //json字符串
        //转为Brand对象
        Brand brand = JSON.parseObject(params, Brand.class);
        //2.调用service添加
        brandService.add(brand);
        //3.响应成功的标识
        response.getWriter().write("success");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

前端页面:
添加页面的提交按钮可以绑定一个单击事件,而该事件绑定的是addBrand 函数,所以添加数据功能的逻辑代码应该写在 addBrand() 函数中。在此方法中需要发送异步请求并将表单中输入的数据作为参数进行传递。
brand.html:

// 添加数据
addBrand() {
    var _this = this;
 
    // 发送ajax请求,添加数据
    axios({
        method:"post",
        url:"http://localhost:8080/brand-case/addServlet",
        data:_this.brand
    }).then(function (resp) {
       	//响应数据的处理逻辑
    })
}

在 then 函数中的匿名函数是成功后的回调函数,而 resp.data 就可以获取到响应回来的数据,如果值是 success 表示数据添加成功。成功后需要做一下逻辑处理:关闭新增对话框窗口,重新查询全部数据,弹出提示消息给用户提示添加成功
在这里插入图片描述将 mounted() 钩子函数中代码改进为:

    mounted(){
      //当页面加载完成后,发送异步请求,获取数据
      this.selectAll();
    },

前端整体代码:

      //添加数据
      addBrand(){
        //console.log(this.brand);
        var _this = this;
        // 发送ajax请求,添加数据
        axios({
          method: "post",
          url: "http://localhost:8080/brand-case/addServlet",
          data: _this.brand
        }).then(function (resp){
          if (resp.data == "success"){
            // 添加成功
            // 关闭窗口
            _this.dialogVisible = false;
            //重新查询数据
            _this.selectAll();
            //添加成功提示信息
            _this.$message({
              message: '恭喜你,添加成功!!',
              type: 'success'
            });
          }

        })
      },

3.4 Servlet代码优化

问题: Web 层的 Servlet 个数太多了,不利于管理和编写
优化: 将Servlet进行归类,对于同一个实体的操作方法写到一个Servlet中,比如:BrandServlet,UserServlet
在这里插入图片描述

实现思路: 为了做到通用,自定义Servlet,使用请求路径进行方法分发,替换HttpServlet的根据请求方式进行方法分发;在发送请求时,请求资源的二级路径(/brandServlet/selectAll)和需要调用的方法名要保持相同,可以通过反射获取方法对象,执行方法
具体实现:
BaseServlet:

/**
 * 替换HttpServet,根据请求的最后一段路径来进行方法分发
 */
public class BaseServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取请求路径
        String uri = req.getRequestURI();   // /brand-case/brand/selectAll
        //获取最后一段路径(方法名)
        int index = uri.lastIndexOf('/');
        String methodName = uri.substring(index+1);   // /selectAll,index+1后selectAll
        
        //2.执行方法
        //2.1 获取BrandServlet字节码对象Class
        //谁调用我(this 所在的方法),我(this)代表谁
        //System.out.println(this); //BrandServlet
        Class<? extends BaseServlet> cls = this.getClass();
        //2.2 获取方法Method对象
        try {
            Method method = cls.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
            //2.3 执行方法
            method.invoke(this,req,resp);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

BrandServlet:

@WebServlet("/brand/*")
public class BrandServlet extends BaseServlet{

    private BrandService brandService = new BrandServiceImpl();
    public void selectAll(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 调用service查询
        List<Brand> brands = brandService.selectAll();
        //2. 转为JSON
        String jsonString = JSON.toJSONString(brands);
        //3. 写数据
        resp.setContentType("text/json;charset=utf-8"); //告知浏览器响应的数据是什么, 告知浏览器使用什么字符集进行解码
        resp.getWriter().write(jsonString);
    }
    public void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //1. 接收品牌的数据
        BufferedReader br = req.getReader();
        String params = br.readLine();  //json字符串
        //转为Brand对象
        Brand brand = JSON.parseObject(params, Brand.class);
        //2.调用service添加
        brandService.add(brand);
        //3.响应成功的标识
        resp.getWriter().write("success");
    }
}

注意:前端代码访问路径也需要修改一下,http://localhost:8080/brand-case/brand/add

3.5 批量删除

整体流程:
在这里插入图片描述
实现:
Dao层:
在 BrandMapper 接口中定义 deleteByIds() 添加方法,由于这里面要用到动态 sql ,属于复杂的sql操作,建议使用映射配置文件
BrandMapper接口:

 /**
     * 批量删除
     * @param ids
     */
void deleteByIds(@Param("ids") int[] ids);

BrandMapper.xml:

<delete id="deleteByIds">
    delete from tb_brand where id in
    <foreach collection="ids" item="id" separator="," open="(" close=")">
        #{id}
    </foreach>
</delete>

Service层:
在 BrandService 接口中定义 deleteByIds() 批量删除的业务逻辑方法,在 BrandServiceImpl 类中重写 deleteByIds() 方法,并进行业务逻辑实现
BrandService 接口:

/**
     * 批量删除
     * @param ids
     */
void deleteByIds( int[] ids);

BrandServiceImpl:

@Override
public void deleteByIds(int[] ids) {
    //2. 获取SqlSession对象
    SqlSession sqlSession = factory.openSession();
    //3. 获取BrandMapper
    BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
 
    //4. 调用方法
    mapper.deleteByIds(ids);
 
    sqlSession.commit();//提交事务
 
    //5. 释放资源
    sqlSession.close();
}

Web层:
在 BrandServlet 类中定义 deleteByIds() 方法。

该方法的逻辑如下:

  • 接收页面提交的数据。页面到时候提交的数据是 json 格式的数据,所以此处需要使用输入流读取数据
  • 接收页面提交的数据。页面到时候提交的数据是 json 格式的数据,所以此处需要使用输入流读取数据
  • 将接收到的数据转换为 int[] 数组
  • 调用 service 的 deleteByIds() 方法进行批量删除的业务逻辑处理
  • 给浏览器响应添加成功的标识,这里直接给浏览器响应 success 字符串表示成功

BrandServlet:

    public void deleteByIds(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //1. 接收id数组 [1,2,3]
        BufferedReader br = req.getReader();
        String params = br.readLine();  //json字符串
        //转为int[]
        int[] ids = JSON.parseObject(params, int[].class);
        //2.调用service添加
        brandService.deleteByIds(ids);
        //3.响应成功的标识
        resp.getWriter().write("success");
    }

前端:
表格复选框绑定了一个 selection-change 事件,该事件是当选择项发生变化时会触发。该事件绑定了 handleSelectionChange 函数,而该函数有一个参数 val ,该参数是获取选中行的数据,如下在这里插入图片描述而我们只需要将所有选中数据的id值提交给服务端即可,获取id的逻辑我们书写在 批量删除 按钮绑定的函数中。在 批量删除 按钮绑定单击事件,并给绑定触发时调用的函数。在Vue对象中的 methods 中定义 deleteByIds() 函数,在该函数中从 multipleSelection 数据模型中获取所选数据的id值。要完成这个功能需要在 Vue 对象中定义一个数据模型 selectedIds:[],在 deleteByIds() 函数中遍历 multipleSelection 数组,并获取到每一个所选数据的id值存储到 selectedIds 数组中
Brand.html:

//2. 发送AJAX请求
var _this = this;
 
// 发送ajax请求,添加数据
axios({
    method:"post",
    url:"http://localhost:8080/brand-case/brand/deleteByIds",
    data:_this.selectedIds
}).then(function (resp) {
    if(resp.data == "success"){
        //删除成功
        // 重新查询数据
        _this.selectAll();
        // 弹出消息提示
        _this.$message({
            message: '恭喜你,删除成功',
            type: 'success'
        });
    }
})

添加确定框逻辑实现:
在这里插入图片描述代码实现:

      //批量删除
      deleteByIds: function () {
        //弹出确认删除的提示框
        this.$confirm('此操作将删除该数据, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          //用户点击确认按钮
          //1.创建id数组,从this.multipleSelection 获取
          for (let i = 0; i < this.multipleSelection.length; i++) {
            let selectionElement = this.multipleSelection[i];
            this.selectedIds[i] = selectionElement.id;
          }
          //2.发生ajax请求
          var _this = this;
          // 发送ajax请求,添加数据
          axios({
            method: "post",
            url: "http://localhost:8080/brand-case/brand/deleteByIds",
            data: _this.selectedIds
          }).then(function (resp) {
            if (resp.data == "success") {
              // 删除成功
              //重新查询数据
              _this.selectAll();
              //添加成功提示信息
              _this.$message({
                message: '删除成功!!',
                type: 'success'
              });
            }
          })
        }).catch(() => {
          //用户点击确认按钮
          this.$message({
            type: 'info',
            message: '已取消删除'
          });
        });
      }

3.6 分页查询

在这里插入图片描述

流程:
在这里插入图片描述实现:
Dao层:
在 BrandMapper 接口中定义 selectByPage() 方法进行分页查询,定义 selectTotalCount() 方法进行统计记录数
BrandMapper 接口:

    /**
     * 分页查询
     * @param begin
     * @param size
     * @return
     */
    @Select("select * from tb_brand limit #{begin}, #{size}")
    @ResultMap("brandResultMap")
    List<Brand> selectByPage(@Param("begin") int begin,@Param("size") int size);

    /**
     * 查询总记录数
     * @return
     */
    @Select("select count(*) from tb_brand")
    int selectTotalCount();

Service层:
在 BrandService 接口中定义 selectByPage() 分页查询数据的业务逻辑方法,在 BrandServiceImpl 类中重写 selectByPage() 方法,并进行业务逻辑实现。
BrandService 接口:

    /**
     * 分页查询
     * @param currentPage 当前页码
     * @param pageSize 每页展示条数
     * @return
     */
    PageBean<Brand> selectByPage(int currentPage,int pageSize);

BrandServiceImpl:

    @Override
    public PageBean<Brand> selectByPage(int currentPage, int pageSize) {
        //2.获取SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //3.获取BrandMapper
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
        //4.计算开始索引
        int begin = (currentPage-1) * pageSize;
        //计算查询条目数
        int size = pageSize;
        //5. 调用方法,查询当前页数据
        List<Brand> rows = brandMapper.selectByPage(begin, size);
        //6.查询总记录数
        int totalCount = brandMapper.selectTotalCount();

        //7.封装PageBean对象
        PageBean<Brand> pageBean = new PageBean<>();
        pageBean.setRows(rows);
        pageBean.setTotalCount(totalCount);

        //8.释放资源
        sqlSession.close();

        return pageBean;
    }

Web层:
在 BrandServlet 类中定义 selectByPage() 方法。
该方法的逻辑如下:
获取页面提交的 当前页码 和 每页显示条目数 两个数据。这两个参数是在url后进行拼接的,格式是 url?currentPage=1&pageSize=5。获取这样的参数需要使用 requet.getparameter() 方法获取。
调用 service 的 selectByPage() 方法进行分页查询的业务逻辑处理
将查询到的数据转换为 json 格式的数据
响应 json 数据

BrandServlet中selectByPage() 方法:

    public void selectByPage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 接收 当前页码 和 每页展示条数  url?currentPage=1&pageSize=5
        String _currentPage = req.getParameter("currentPage");
        String _pageSize = req.getParameter("pageSize");

        int currentPage = Integer.parseInt(_currentPage);
        int pageSize = Integer.parseInt(_pageSize);

        //2. 调用service进行查询
        PageBean<Brand> pageBean = brandService.selectByPage(currentPage, pageSize);
        //3. 转为JSON
        String jsonString = JSON.toJSONString(pageBean);
        //3. 写数据
        resp.setContentType("text/json;charset=utf-8"); //告知浏览器响应的数据是什么, 告知浏览器使用什么字符集进行解码
        resp.getWriter().write(jsonString);
    }

测试一下:
在浏览器上地址栏输入 http://localhost:8080/brand-case/brand/selectByPage?currentPage=1&pageSize=5 ,查询到以下数据如下数据则后端代码没问题。
在这里插入图片描述
前端:
selectAll() 函数之前是查询所有数据,现需要改成分页查询。
请求路径应改为需要修改 ,其中 currentPage 和 pageSize 是需要携带的参数,分别是 当前页码 和 每页显示的条目数。
刚才对后端代码进行测试可以看出响应回来的数据,所以在异步请求的成功回调函数(then 中的匿名函数)中给页面表格的数据模型赋值。响应的数据中还有总记录数,要进行总记录数展示需要在页面绑定数据模型(该数据模型需要在Vue对象中声明出来)

var _this = this;
axios({
    method:"post",
    url:"http://localhost:8080/brand-case/brand/selectByPage?currentPage=1&pageSize=5"
}).then(resp =>{
    //设置表格数据
    _this.tableData = resp.data.rows; // {rows:[],totalCount:100}
    //设置总记录数
    _this.totalCount = resp.data.totalCount;
})

分页组件给 当前页码 和 每页显示的条目数 都绑定了数据模型,所以 selectAll() 函数中发送异步请求的资源路径中不能将当前页码和 每页显示条目数写死

var _this = this;
axios({
    method:"post",
    url:"http://localhost:8080/brand-case/brand/selectByPage?currentPage="+this.currentPage+"&pageSize=" + this.pageSize
}).then(resp =>{
    //设置表格数据
    _this.tableData = resp.data.rows; // {rows:[],totalCount:100}
    //设置总记录数
    _this.totalCount = resp.data.totalCount;
})

改变每页条目数:
当我们改变每页显示的条目数后,需要重新发送异步请求。分页组件代码@size-change 就是每页显示的条目数发生变化时会触发的事件,而该事件绑定了一个 handleSizeChange 函数:

handleSizeChange(val) { //我们选择的是 ‘5条/页’ 此值就是 5.而我们选择了 `10条/页` 此值就是 10
    // 重新设置每页显示的条数
    this.pageSize  = val; 
    //调用 selectAll 函数重新分页查询数据
    this.selectAll();
}

改变当前页码:
当我们改变页码时,需要重新发送异步请求。分页组件代码@current-change 就是页码发生变化时会触发的事件,该事件绑定了一个 handleSizeChange 函数:

handleCurrentChange(val) { //val 就是改变后的页码
    // 重新设置当前页码
    this.currentPage  = val;
    //调用 selectAll 函数重新分页查询数据
    this.selectAll();
}

3.7 条件查询

需要考虑的问题:
在这里插入图片描述根据上面三个问题的明确,我们就可以确定sql语句:
在这里插入图片描述

流程:
在这里插入图片描述
实现:
Dao层:
在 BrandMapper 接口中定义 selectByPageAndCondition() 方法 和 selectTotalCountByCondition 方法,用来进行条件分页查询功能;由于这是一个复杂的查询语句,需要使用动态sql;所以我们在映射配置文件中书写 sql 语句。brand_name 字段和 company_name 字段需要进行模糊查询,所以需要使用 % 占位符。
BrandMapper 接口:

/**
     * 分页条件查询
     * @param begin
     * @param size
     * @return
     */
List<Brand> selectByPageAndCondition(@Param("begin") int begin,@Param("size") int size,@Param("brand") Brand brand);
 
/**
     * 根据条件查询总记录数
     * @return
     */
int selectTotalCountByCondition(Brand brand);

BrandMapper.xml:

<!--查询满足条件的数据并进行分页-->
<select id="selectByPageAndCondition" resultMap="brandResultMap">
    select *
    from tb_brand
    <where>
        <if test="brand.brandName != null and brand.brandName != '' ">
            and  brand_name like #{brand.brandName}
        </if>
 
        <if test="brand.companyName != null and brand.companyName != '' ">
            and  company_name like #{brand.companyName}
        </if>
 
        <if test="brand.status != null">
            and  status = #{brand.status}
        </if>
    </where>
    limit #{begin} , #{size}
</select>
 
<!--查询满足条件的数据条目数-->
<select id="selectTotalCountByCondition" resultType="java.lang.Integer">
    select count(*)
    from tb_brand
    <where>
        <if test="brandName != null and brandName != '' ">
            and  brand_name like #{brandName}
        </if>
 
        <if test="companyName != null and companyName != '' ">
            and  company_name like #{companyName}
        </if>
 
        <if test="status != null">
            and  status = #{status}
        </if>
    </where>
</select>

Service层:
在 BrandService 接口中定义 selectByPageAndCondition() 分页查询数据的业务逻辑方法,在 BrandServiceImpl 类中重写 selectByPageAndCondition() 方法,并进行业务逻辑实现
BrandService 接口:

 /**
     * 分页条件查询
     * @param currentPage
     * @param pageSize
     * @param brand
     * @return
     */
PageBean<Brand>  selectByPageAndCondition(int currentPage,int pageSize,Brand brand);

BrandServiceImpl:

 @Override
    public PageBean<Brand> selectByPageAndCondition(int currentPage, int pageSize, Brand brand) {
        //2. 获取SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //3. 获取BrandMapper
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
 
 
        //4. 计算开始索引
        int begin = (currentPage - 1) * pageSize;
        // 计算查询条目数
        int size = pageSize;
 
        // 处理brand条件,模糊表达式
        String brandName = brand.getBrandName();
        if (brandName != null && brandName.length() > 0) {
            brand.setBrandName("%" + brandName + "%");
        }
 
        String companyName = brand.getCompanyName();
        if (companyName != null && companyName.length() > 0) {
            brand.setCompanyName("%" + companyName + "%");
        }
 
        //5. 查询当前页数据
        List<Brand> rows = mapper.selectByPageAndCondition(begin, size, brand);
 
        //6. 查询总记录数
        int totalCount = mapper.selectTotalCountByCondition(brand);
 
        //7. 封装PageBean对象
        PageBean<Brand> pageBean = new PageBean<>();
        pageBean.setRows(rows);
        pageBean.setTotalCount(totalCount);
 
        //8. 释放资源
        sqlSession.close();
 
        return pageBean;

Web层:
在 BrandServlet 类中定义 selectByPageAndCondition() 方法。
该方法的逻辑如下:
1、获取页面提交的 当前页码 和 每页显示条目数 两个数据。这两个参数是在url后进行拼接的,格式是 url?currentPage=1&pageSize=5。获取这样的参数需要使用 requet.getparameter() 方法获取。
2、获取页面提交的 条件数据 ,并将数据封装到一个Brand对象中。由于这部分数据到时候是需要以 json 格式进行提交的,所以我们需要通过流获取数据
3、调用 service 的 selectByPageAndCondition() 方法进行分页查询的业务逻辑处理
4、将查询到的数据转换为 json 格式的数据
5、响应 json 数据

selectByPageAndCondition() 方法:

public void selectByPageAndCondition(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //1. 接收 当前页码 和 每页展示条数    url?currentPage=1&pageSize=5
    String _currentPage = request.getParameter("currentPage");
    String _pageSize = request.getParameter("pageSize");
 
    int currentPage = Integer.parseInt(_currentPage);
    int pageSize = Integer.parseInt(_pageSize);
 
    // 获取查询条件对象
    BufferedReader br = request.getReader();
    String params = br.readLine();//json字符串
 
    //转为 Brand
    Brand brand = JSON.parseObject(params, Brand.class);
 
 
    //2. 调用service查询
    PageBean<Brand> pageBean = brandService.selectByPageAndCondition(currentPage,pageSize,brand);
 
    //2. 转为JSON
    String jsonString = JSON.toJSONString(pageBean);
    //3. 写数据
    response.setContentType("text/json;charset=utf-8");
    response.getWriter().write(jsonString);
}

前端:
查询表单绑定查询条件对象模型;给 查询 按钮绑定了 onSubmit() 函数,而在 onSubmit() 函数中只需要调用 selectAll() 函数进行条件分页查询。页面加载完成后发送异步请求,需要携带当前页码、每页显示条数、查询条件对象。当前页码 和 每页显示条数 这两个参数拼接到 URL 的后面;查询条件对象 这个参数需要以 json 格式提交给后端程序

//查询方法
      onSubmit() {
        //console.log(this.brand);
        this.selectAll();
      },
// 查询所有的方法
      selectAll() {
        var _this = this;

        axios({
          method: "post",
          url: "http://localhost:8080/brand-case/brand/selectByPageAndCondition?currentPage="+this.currentPage+"&pageSize="+this.pageSize,
          data: this.brand
        }).then(resp => {
          //设置表格数据
          _this.tableData = resp.data.rows;  //{row:[],totalCount:100}
          //设置总记录数
          _this.totalCount = resp.data.totalCount;
        })
      }

优化一下状态显示:
在这里插入图片描述在这里插入图片描述

前端代码优化:箭头函数
在这里插入图片描述

then里匿名函数的this特点:
需要在成功的回调函数(也就是then 函数中的匿名函数)中使用this,都需要在外边使用 _this 记录一下 this 所指向的对象;因为在外边的 this 表示的是 Vue 对象,而回调函数中的 this 表示的是window对象。
使用箭头函数:
可以使用 ECMAScript6 中的新语法(箭头函数)来替代传统函数function() {}

axios({
    method:"post",
    url:"http://localhost:8080/brand-case/brand/selectByPageAndCondition?currentPage="+this.currentPage+"&pageSize="+this.pageSize,
    data:this.brand
}).then((resp) => {
 
    //设置表格数据
    this.tableData = resp.data.rows; // {rows:[],totalCount:100}
    //设置总记录数
    this.totalCount = resp.data.totalCount;
})

参考文章

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值