Detailed explanation of JavaWeb front-end framework VUE and Element components


foreword

提示:这里可以添加本文要记录的大概内容:


1. Front-end framework - VUE

Today's goal:

  • Ability to use common commands and interpolation expressions in VUE
  • Ability to use the VUE lifecycle function mounted
  • Ability to make simple Element page modifications
  • Able to complete all query functions
  • Ability to add functionality

1.1 Overview

Next we learn a front-end framework, which is VUE.

Vue is a set of front-end frameworks that exempts DOM operations in native JavaScript and simplifies writing.

We have also learned before that the back-end framework Mybatisis Mybatisused to simplify jdbccode writing; but VUEthe front-end framework is used to simplify JavaScriptcode writing. We made a comprehensive case the day before, in which a lot of DOM operations were performed, as follows

insert image description here

VUEAfter learning , we don't need to write this part of the code anymore. VUESo how to simplify DOM writing?

==Based on the idea of ​​MVVM (Model-View-ViewModel), the two-way binding of data is realized, and the focus of programming is on the data. ==Before we focused on the DOM operation; but to understand MVVMthe idea , we must first talk about MVCthe idea, as shown in the figure below is MVCthe idea diagram
insert image description here

C is our js code, M is the data, and V is the content displayed on the page. The following picture is the code we wrote before

insert image description here

MVCThoughts cannot be two-way bound. Two-way binding means that when the data model data changes, the page display will change accordingly, and if the form data changes, the bound model data will also change accordingly. Next, let's talk about MVVMideas , the following figure is a diagram of three components

The in the figure Modelis our data, Viewwhich is the view, that is, the page label, the content that the user can see through the browser; Modeland Vieware ViewModeltwo-way bound through the object, and ViewModelthe object is Vueprovided by . Next, let's take a look at the effect of two-way binding. The following figure is the code prepared in advance. The input box is bound to usernamethe model data, and the model{ {}} data is also bound on the page.username

Open this page through a browser and you can see the following page

When we enter content in the input box, and the content we input is displayed in real time behind the input box, this is the effect of two-way binding.

1.2 Quick Start

Vue is relatively simple to use, and it is divided into the following three steps:

  1. Create a new HTML page and import the Vue.js file

    <script src="js/vue.js"></script>
    
  2. In the JS code area, create a Vue core object for data binding

    new Vue({
          
          
        el: "#app",
        data() {
          
          
            return {
          
          
                username: ""
            }
        }
    });
    

    When creating a Vue object, a js object needs to be passed, and the following attributes are required in the object:

    • el: Used to specify which tags are managed by Vue. The value #appof appneeds to be the id attribute value of the managed label
    • data: used to define the data model
    • methods: Used to define functions. This we will use later
  3. write view

    <div id="app">
        <input name="username" v-model="username" >
        {
         
         {username}}
    </div>
    

    { {}}It is defined in Vue 插值表达式, and the data model is written in it, and the data value of the model will be displayed in this position at that time.

The overall code is as follows:

<!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(){
      
        // data() 是 ECMAScript 6 版本的新的写法
            return {
      
      
                username:""
            }
        }

        /*data: function () {
            return {
                username:""
            }
        }*/
    });

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

1.3 Vue directives

**Instructions: **Special attributes with a v- prefix on HTML tags, different instructions have different meanings. For example: v-if, v-for...

Commonly used commands are:

instruction effect
v-bind Bind attribute values ​​for HTML tags, such as setting href, css style, etc.
v-model Create two-way data bindings on form elements
v-on Binding events for HTML tags
v-if Render an element conditionally, render when the judgment is true, otherwise not render
v-else
v-else-if
v-show Display an element according to the condition, the difference is that the value of the display attribute is switched
v-for List rendering, traversing the elements of the container or the properties of the object

Next, let's learn these instructions one by one.

1.3.1 v-bind & v-model directives

  • v-bind

    This directive can bind model data to the original attribute of the tag. In this way, the model data changes, and the tag attribute value also changes accordingly.

    For example:

    <a v-bind:href="url">百度一下</a>
    

    The above v-bind:"can be simplified :as follows:

    <!--
    	v-bind 可以省略
    -->
    <a :href="url">百度一下</a>
    
  • v-model

    This directive can bind model data to form item tags. In this way, a two-way binding effect can be achieved. For example:

    <input name="username" v-model="username">
    

Code demo:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <a v-bind:href="url">点击一下</a>
    <a :href="url">点击一下</a>
    <input v-model="url">
</div>

<script src="js/vue.js"></script>
<script>
    //1. 创建Vue核心对象
    new Vue({
      
      
        el:"#app",
        data(){
      
      
            return {
      
      
                username:"",
                url:"https://www.baidu.com"
            }
        }
    });
</script>
</body>
</html>

Open the above page through the browser, and use the check to view the path of the hyperlink, which will change according to the path entered in the input box, because the hyperlink and the input box are bound to the same model data

1.3.2 v-on directive

We define a button on the page, and use v-onthe command . The html code is as follows

<input type="button" value="一个按钮" v-on:click="show()">

v-onWhen using, you can also use a simplified way of writing, v-on:replace with @, the html code is as follows

<input type="button" value="一个按钮" @click="show()">

The binding of the above code show()needs methodsto be defined in the property of the Vue object

new Vue({
    
    
    el: "#app",
    methods: {
    
    
        show(){
    
    
            alert("我被点了");
        }
    }
});

Note: v-on:The following event name is the original event attribute name before removing on.

For example:

  • Click event: The event attribute name is onclick, and it is used in vuev-on:click
  • Lost focus event: the event attribute name is onblur, and when used in vuev-on:blur

The overall page code is as follows:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <input type="button" value="一个按钮" v-on:click="show()"><br>
    <input type="button" value="一个按钮" @click="show()">
</div>
<script src="js/vue.js"></script>
<script>
    //1. 创建Vue核心对象
    new Vue({
      
      
        el:"#app",
        data(){
      
      
            return {
      
      
                username:"",
            }
        },
        methods:{
      
      
            show(){
      
      
                alert("我被点了...");
            }
        }
    });
</script>
</body>
</html>

1.3.3 Condition judgment instruction

Next, let's demonstrate it through code. Define counta , as follows

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

Now to achieve, when the data of countthe model is 3, div1the content is displayed on the page; when the data of countthe model is 4, div2the content is displayed on the page; countwhen the model data is other values, it is displayed on the page div3. Here, in order to dynamically change the value countof , another input box is defined to bind countthe model data. The html code is as follows:

<div id="app">
    <div v-if="count == 3">div1</div>
    <div v-else-if="count == 4">div2</div>
    <div v-else>div3</div>
    <hr>
    <input v-model="count">
</div>

The overall page code is as follows:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <div v-if="count == 3">div1</div>
    <div v-else-if="count == 4">div2</div>
    <div v-else>div3</div>
    <hr>
    <input v-model="count">
</div>

<script src="js/vue.js"></script>
<script>
    //1. 创建Vue核心对象
    new Vue({
      
      
        el:"#app",
        data(){
      
      
            return {
      
      
                count:3
            }
        }
    });
</script>
</body>
</html>

Open the page through the browser and enter different values ​​in the input box, the effect is as follows

Then we are looking at the effect of v-showthe instruction . If count the value of the model data is 3, div v-showthe content , otherwise it will not be displayed. The html page code is as follows

<div v-show="count == 3">div v-show</div>
<br>
<input v-model="count">

The effect of opening the browser is as follows:

Through the above demonstration, it is found v-showthat and v-ifhave the same effect, so what is the difference between them? We view the source code against the browser's inspection capabilities

image-20210831154759672

It can be seen from the above figure that the principle of v-shownot displaying is to add displaya css attribute to the corresponding label, and set the attribute value to none, thus achieving the hidden effect. v-ifThe instruction is that it will not be rendered at all when the condition is not met.

1.3.4 v-for directive

This instruction knows that it is used for traversal when you see its name. The format used by this instruction is as follows:

<标签 v-for="变量名 in 集合模型数据">
    {
   
   {变量名}}
</标签>

Note: The label needs to be cycled, and v-forthe instruction is written on that label.

If you need to use the index of the collection model data on the page, you need to use the following format:

<标签 v-for="(变量名,索引变量) in 集合模型数据">
    <!--索引变量是从0开始,所以要表示序号的话,需要手动的加1-->
   {
   
   {索引变量 + 1}} {
   
   {变量名}}
</标签>

Code demo:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <div v-for="addr in addrs">
        {
   
   {addr}} <br>
    </div>

    <hr>
    <div v-for="(addr,i) in addrs">
        {
   
   {i+1}}--{
   
   {addr}} <br>
    </div>
</div>

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

    //1. 创建Vue核心对象
    new Vue({
      
      
        el:"#app",
        data(){
      
      
            return {
      
      
                addrs:["北京","上海","西安"]
            }
        }
    });
</script>
</body>
</html>

The effect of opening it through a browser is as follows

1.4 Life cycle

Eight phases of the life cycle: Every time a life cycle event is triggered, a life cycle method is automatically executed, and these life cycle methods are also called hook methods.

The figure below shows the entire process from creating Vue to effecting Vue objects and the hook functions corresponding to each stage provided by Vue official website

Seeing the picture above, you don’t need to pay too much attention to this picture. We only need mountedto .

mounted: The mount is complete, Vue is initialized successfully, and the HTML page is rendered successfully. And later in this method we willSend an asynchronous request to load data.

1.5 case

1.5.1 Requirements

Use Vue to simplify the brand list data query and add functions we did after learning ajax the day before

This case just uses Vue to optimize the front-end code, and the back-end code does not need to be modified.

1.5.2 Query all functions

  1. Introduce the vue js file in the brand.html page

    <script src="js/vue.js"></script>
    
  2. Create a Vue object

    • Define model data in Vue objects
    • Send an asynchronous request in the hook function and assign the response data to the data model
    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;
            })
        }
    })
    
  3. modify view

    • Definition <div id="app"></div>, specifying that the divtag is managed by Vue

    • bodyCopy all the content in the tag as divin the above tag

    • Delete the redundant data rows of the table, leaving only one

    • Use v-forthe directive

      <tr v-for="(brand,i) in brands" align="center">
          <td>{
             
             {i + 1}}</td>
          <td>{
             
             {brand.brandName}}</td>
          <td>{
             
             {brand.companyName}}</td>
          <td>{
             
             {brand.ordered}}</td>
          <td>{
             
             {brand.description}}</td>
          <td>{
             
             {brand.statusStr}}</td>
          <td><a href="#">修改</a> <a href="#">删除</a></td>
      </tr>
      

The overall page code is as follows:

<!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" align="center">
            <td>{
   
   {i + 1}}</td>
            <td>{
   
   {brand.brandName}}</td>
            <td>{
   
   {brand.companyName}}</td>
            <td>{
   
   {brand.ordered}}</td>
            <td>{
   
   {brand.description}}</td>
            <td>{
   
   {brand.statusStr}}</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>

1.5.3 Add function

The page operation effect is as follows:

The overall process is as follows

Note: The key point of the front-end code is to use v-modelthe command to bind the model data to the label item, and use the two-way binding feature to submit the data when sending an asynchronous request.

  1. Introduce the vue js file on the addBrand.html page

    <script src="js/vue.js"></script>
    
  2. Create a Vue object

    • Define model data in Vue objectsbrand
    • Define a submitForm()function to 提交provide a binding function for the button
    • Send an ajax request in submitForm()the function and brandpass the model data as a parameter
    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";
                    }
                })
    
            }
        }
    })
    
  3. modify view

    • Definition <div id="app"></div>, specifying that the divtag is managed by Vue

    • bodyCopy all the content in the tag as divin the above tag

    • Bind model data to each form item tag. Finally, these data are encapsulated into brandobjects

      <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>
      

The overall page code is as follows:

<!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>

Through the above optimization, the front-end code is indeed simplified a lot. But the page is still not very good-looking, so let's learn Element, which can beautify the page.

Two, Element components

2.0 Overview of Element components

Element: It is a set of Vue-based website component library provided by the front-end development team of Ele.me, which is used to quickly build web pages.

Element provides many components (parts that make up web pages) for us to use. Such as hyperlinks, buttons, pictures, tables, etc.~

The left side of the picture below is the button we see when writing the page, and the right side of the picture above is the page effect provided by Element, and the effect is clear at a glance.

We learn Element is actually learning how to copy components from the official website to our own pages and modify them. The official website URL is

https://element.eleme.cn/#/zh-CN

Enter the official website to see the following page

insert image description here

Next click directly 组件, the page is as follows

insert image description here

2.1 Quick Start

  1. 04-资料\02-elementCopy the folder under resources element-uidirectly webappto . The directory structure is as follows

  2. Create a page and introduce Element's css, js files and Vue.js into the page

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

    Element is based on Vue, so you must create a Vue object when using Element

    <script>
        new Vue({
            
            
            el:"#app"
        })
    </script>
    
  4. Copy the Element component code from the official website

    Find it in the left menu bar Button 按钮, then find the button style you like, click it 显示代码, and the corresponding code will be displayed below, just copy the code to our own page.

The overall page code is as follows:

<!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>
    <el-row>
        <el-button plain>朴素按钮</el-button>
        <el-button type="primary" plain>主要按钮</el-button>
        <el-button type="success" plain>成功按钮</el-button>
        <el-button type="info" plain>信息按钮</el-button>
        <el-button type="warning" plain>警告按钮</el-button>
        <el-button type="danger" plain>危险按钮</el-button>
    </el-row>

    <el-row>
        <el-button round>圆角按钮</el-button>
        <el-button type="primary" round>主要按钮</el-button>
        <el-button type="success" round>成功按钮</el-button>
        <el-button type="info" round>信息按钮</el-button>
        <el-button type="warning" round>警告按钮</el-button>
        <el-button type="danger" round>危险按钮</el-button>
    </el-row>

    <el-row>
        <el-button icon="el-icon-search" circle></el-button>
        <el-button type="primary" icon="el-icon-edit" circle></el-button>
        <el-button type="success" icon="el-icon-check" circle></el-button>
        <el-button type="info" icon="el-icon-message" circle></el-button>
        <el-button type="warning" icon="el-icon-star-off" circle></el-button>
        <el-button type="danger" icon="el-icon-delete" circle></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.2 Element layout

Element provides two layout methods, namely:

  • Layout layout
  • Container layout container

2.2.1 Layout Partial

Create layouts quickly and easily with basic 24 columns. That is, a row is divided into 24 columns by default, and the number of columns occupied by each column is set according to the page requirements.

Find it in the left menu bar Layout 布局, then find the button style you like, click it 显示代码, and the corresponding code will be displayed below. The displayed code has styles and html tags. Copy the style into headthe tag , and copy the html tag <div id="app"></div>into the tag.

The overall page code is as follows:

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

    <style>
        .el-row {
      
      
            margin-bottom: 20px;
        }
        .el-col {
      
      
            border-radius: 4px;
        }
        .bg-purple-dark {
      
      
            background: #99a9bf;
        }
        .bg-purple {
      
      
            background: #d3dce6;
        }
        .bg-purple-light {
      
      
            background: #e5e9f2;
        }
        .grid-content {
      
      
            border-radius: 4px;
            min-height: 36px;
        }
        .row-bg {
      
      
            padding: 10px 0;
            background-color: #f9fafc;
        }
    </style>
</head>
<body>
<div id="app">
    <el-row>
        <el-col :span="24"><div class="grid-content bg-purple-dark"></div></el-col>
    </el-row>
    <el-row>
        <el-col :span="12"><div class="grid-content bg-purple"></div></el-col>
        <el-col :span="12"><div class="grid-content bg-purple-light"></div></el-col>
    </el-row>
    <el-row>
        <el-col :span="8"><div class="grid-content bg-purple"></div></el-col>
        <el-col :span="8"><div class="grid-content bg-purple-light"></div></el-col>
        <el-col :span="8"><div class="grid-content bg-purple"></div></el-col>
    </el-row>
    <el-row>
        <el-col :span="6"><div class="grid-content bg-purple"></div></el-col>
        <el-col :span="6"><div class="grid-content bg-purple-light"></div></el-col>
        <el-col :span="6"><div class="grid-content bg-purple"></div></el-col>
        <el-col :span="6"><div class="grid-content bg-purple-light"></div></el-col>
    </el-row>
    <el-row>
        <el-col :span="4"><div class="grid-content bg-purple"></div></el-col>
        <el-col :span="4"><div class="grid-content bg-purple-light"></div></el-col>
        <el-col :span="4"><div class="grid-content bg-purple"></div></el-col>
        <el-col :span="4"><div class="grid-content bg-purple-light"></div></el-col>
        <el-col :span="4"><div class="grid-content bg-purple"></div></el-col>
        <el-col :span="4"><div class="grid-content bg-purple-light"></div></el-col>
    </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>

Now you need to add a line, which requires the line to display 8 grids. By calculating, each grid occupies 3 columns. The specific html code is as follows

<!--
添加一行,8个格子  24/8 = 3
-->
<el-row>
    <el-col :span="3"><div class="grid-content bg-purple"></div></el-col>
    <el-col :span="3"><div class="grid-content bg-purple-light"></div></el-col>
    <el-col :span="3"><div class="grid-content bg-purple"></div></el-col>
    <el-col :span="3"><div class="grid-content bg-purple-light"></div></el-col>
    <el-col :span="3"><div class="grid-content bg-purple"></div></el-col>
    <el-col :span="3"><div class="grid-content bg-purple-light"></div></el-col>
    <el-col :span="3"><div class="grid-content bg-purple"></div></el-col>
    <el-col :span="3"><div class="grid-content bg-purple-light"></div></el-col>
</el-row>

2.2.2 Container layout container

The container component used for layout is convenient for quickly building the basic structure of the page. The following figure is the layout container effect.

The following figure is an example of the Container layout container provided by the official website:

The effect code includes styles, page tags, and model data. <style>Copy the style inside to headthe tag of our own page; copy the html tag to <div id="app"></div>the tag , and then copy the data model tovue the object .data()

The overall page code is as follows:

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

    <style>
        .el-header {
      
      
            background-color: #B3C0D1;
            color: #333;
            line-height: 60px;
        }

        .el-aside {
      
      
            color: #333;
        }
    </style>
</head>
<body>
<div id="app">
    <el-container style="height: 500px; border: 1px solid #eee">
        <el-aside width="200px" style="background-color: rgb(238, 241, 246)">
            <el-menu :default-openeds="['1', '3']">
                <el-submenu index="1">
                    <template slot="title"><i class="el-icon-message"></i>导航一</template>
                    <el-menu-item-group>
                        <template slot="title">分组一</template>
                        <el-menu-item index="1-1">选项1</el-menu-item>
                        <el-menu-item index="1-2">选项2</el-menu-item>
                    </el-menu-item-group>
                    <el-menu-item-group title="分组2">
                        <el-menu-item index="1-3">选项3</el-menu-item>
                    </el-menu-item-group>
                    <el-submenu index="1-4">
                        <template slot="title">选项4</template>
                        <el-menu-item index="1-4-1">选项4-1</el-menu-item>
                    </el-submenu>
                </el-submenu>
                <el-submenu index="2">
                    <template slot="title"><i class="el-icon-menu"></i>导航二</template>
                    <el-submenu index="2-1">
                        <template slot="title">选项1</template>
                        <el-menu-item index="2-1-1">选项1-1</el-menu-item>
                    </el-submenu>
                </el-submenu>
                <el-submenu index="3">
                    <template slot="title"><i class="el-icon-setting"></i>导航三</template>
                    <el-menu-item-group>
                        <template slot="title">分组一</template>
                        <el-menu-item index="3-1">选项1</el-menu-item>
                        <el-menu-item index="3-2">选项2</el-menu-item>
                    </el-menu-item-group>
                    <el-menu-item-group title="分组2">
                        <el-menu-item index="3-3">选项3</el-menu-item>
                    </el-menu-item-group>
                    <el-submenu index="3-4">
                        <template slot="title">选项4</template>
                        <el-menu-item index="3-4-1">选项4-1</el-menu-item>
                    </el-submenu>
                </el-submenu>
            </el-menu>
        </el-aside>

        <el-container>
            <el-header style="text-align: right; font-size: 12px">
                <el-dropdown>
                    <i class="el-icon-setting" style="margin-right: 15px"></i>
                    <el-dropdown-menu slot="dropdown">
                        <el-dropdown-item>查看</el-dropdown-item>
                        <el-dropdown-item>新增</el-dropdown-item>
                        <el-dropdown-item>删除</el-dropdown-item>
                    </el-dropdown-menu>
                </el-dropdown>
                <span>王小虎</span>
            </el-header>

            <el-main>
                <el-table :data="tableData">
                    <el-table-column prop="date" label="日期" width="140">
                    </el-table-column>
                    <el-table-column prop="name" label="姓名" width="120">
                    </el-table-column>
                    <el-table-column prop="address" label="地址">
                    </el-table-column>
                </el-table>
            </el-main>
        </el-container>
    </el-container>
</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",
        data() {
      
      
            const item = {
      
      
                date: '2016-05-02',
                name: '王小虎',
                address: '上海市普陀区金沙江路 1518 弄'
            };
            return {
      
      
                tableData: Array(20).fill(item)
            }
        }
    })
</script>
</body>
</html>

2.3 Case

The other components we learn by completing a page.

We want to complete the following page effect

To complete the page, we need to analyze the page first to see where the page is composed, and then copy and modify it on the official website. The page has the following components in total

insert image description here

Another one is that when we click 新增the button , a dialog box will pop up in the middle of the page, as follows

2.3.1 Prepare the basic page

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
	
</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.2 Complete the form display

The overall idea of ​​using Element iscopy + modify

2.3.2.1 Copy

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-Dwm36pjK-1659351169452)(assets/image-20210831185937618.png)]

Find Table 表格and , the main body on the right will locate the table, find the table effect we need (as shown in the figure above), and click 显示代码to see the code of this table.

Copy the html tags <div id="app"></div>into , as follows:

Copy the css style to headthe tag , as follows

Copy the method and model data to the location specified by the Vue object

After the copy is completed, open it through the browser to see the effect of the table

[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-Lo2ugx9m-1659351169452)(assets/image-20210831191234876.png)]

The table effect comes out, but the header and data displayed are not what we want, so the page code needs to be modified next.

2.3.2.2 Modification
  1. Modify header and data

    Below is an illustration of the analysis performed on the form code. Modify the number of columns and column names according to the instructions in the figure below

    After modifying the page, you need to modify the bound model data. The following figure is an illustration of the analysis of the model data

  2. Add an action column to the table

    Copy a column from the previous table and modify it. The button is copied and modified from Button 按钮the component

  3. Add checkbox column and label column to the table

    Add check boxes and label columns to the table, the effect is as follows
    insert image description here

    This effect is also copied from the official website of Element, first find the corresponding table effect, and then copy its corresponding code into our code, the following is the effect diagram and code of the official website of the check box column

insert image description here

It should be noted here that there is an event on <el-table>the tag @selection-change="handleSelectionChange". The function bound here also needs to be copied from the official website to our own page code. The function code is as follows:

insert image description here

From this function, it is found that a model data is needed multipleSelection , so the model data needs to be defined

The label column is also copied and modified in the same way.

2.3.3 Complete search form display

Find the horizontal form effect on the Element official website, then copy the code and modify it
insert image description here

显示代码After clicking on the above , the corresponding code will be displayed, and the following is an illustration of the analysis of this part of the code

[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-RUNIJD8F-1659351169454)(assets/image-20210831194835721.png)]

Then modify the code according to the effect we want.

2.3.4 Complete batch deletion and add button display

Find a button with a coloring effect from the Element official website, and copy the code to our own page

2.3.5 Complete the dialog box display

Find the dialog box on the Element official website, as follows:

The code provided by the official website is analyzed below

The model data analyzed in the above figure needs to be defined in the Vue object.

2.3.6 Complete the pagination bar display

Find it on the official website of Element Pagination 分页, and find the effect we need in the main part of the page, as follows

Click 显示代码to find the 完整功能corresponding code, and then analyze the code

The above code attribute description:

  • page-size: number of entries to display per page

  • page-sizes: Display the option settings of the quantity selector on each page.

    :page-sizes="[100,200,300,400]"The corresponding page effect is as follows:

  • currentPage: current page number. We click on that page number, and the value of this attribute is a few.

  • total:total. It is used to set the total number of data entries. After setting this property, Element will automatically calculate how many pages need to be divided and show us the corresponding page number.

Event description:

  • size-change:fired when the pageSize changes. That is, when we change the number of items displayed on each page, this event will trigger.
  • current-change:fired when the currentPage changes. That is, when we click on other page numbers, the event will be triggered.

2.3.7 Complete page code

<!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="brand" 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"
                    align="center"
                    label="排序">
            </el-table-column>
            <el-table-column
                    prop="status"
                    align="center"
                    label="当前状态">
            </el-table-column>
            <el-table-column
                    align="center"
                    label="操作">
                <el-row>
                    <el-button type="primary">修改</el-button>
                    <el-button type="danger">删除</el-button>
                </el-row>
            </el-table-column>

        </el-table>
    </template>

    <!--分页工具条-->
    <el-pagination
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
            :current-page="currentPage"
            :page-sizes="[5, 10, 15, 20]"
            :page-size="5"
            layout="total, sizes, prev, pager, next, jumper"
            :total="400">
    </el-pagination>

</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",
        methods: {
      
      
            tableRowClassName({
       
       row, rowIndex}) {
      
      
                if (rowIndex === 1) {
      
      
                    return 'warning-row';
                } else if (rowIndex === 3) {
      
      
                    return 'success-row';
                }
                return '';
            },
            // 复选框选中后执行的方法
            handleSelectionChange(val) {
      
      
                this.multipleSelection = val;

                console.log(this.multipleSelection)
            },
            // 查询方法
            onSubmit() {
      
      
                console.log(this.brand);
            },
            // 添加数据
            addBrand(){
      
      
                console.log(this.brand);
            },
            //分页
            handleSizeChange(val) {
      
      
                console.log(`每页 ${ 
        val}`);
            },
            handleCurrentChange(val) {
      
      
                console.log(`当前页: ${ 
        val}`);
            }
        },
        data() {
      
      
            return {
      
      
                // 当前页码
                currentPage: 4,
                // 添加数据对话框是否展示的标记
                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>

3. Comprehensive case

3.1 Function introduction

The above are the functions we want to achieve in the comprehensive case. In addition to the function of adding, deleting, modifying and querying data, there are also some complex functions, such as 批量删除, 分页查询, 条件查询and other functions

  • 批量删除Function: There is a checkbox in front of each piece of data. When I select multiple pieces of data and click 批量删除the button , a request will be sent to the backend and multiple pieces of data specified in the database will be deleted.
  • 分页查询Function: When there is a lot of data in the database, it is impossible for us to display all the data in one page. At this time, we need to display the data in pages.
  • 条件查询Function: When the database is large, we need to accurately query some data we want to see. At this time, we need to query by condition.

修改品牌The and functions here 删除品牌are not explained in the course, and are left as exercises for students.

3.2 Environment preparation

Environmental preparation We mainly complete the following two things

  • Import the brand-case module of the data into the idea
  • Execute the tb_brand.sql script provided in the data

3.2.1 Project preparation

04-资料\01-初始工程Import brand-casethe project in to our own idea. The project structure is as follows:

3.2.2 Create table

The following is the statement to create the table

-- 删除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);

3.3 Query all functions

[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-qkTxr4vn-1659351169455)(../../../../../Chuanzhi Podcast/ 2021/web stage document writing/JavaWeb course documentation/day14-comprehensive case/assets/image-20210825200138600.png)]

As shown in the figure above, it is to query the effect of displaying all brand data on the page. To achieve this function, you must first understand the following issues:

  • When to send an asynchronous request?

    All the branding data needs to be visible on the page once the page has loaded. So write the code to send an asynchronous request in mounted()this constructor.

  • Does the request need to carry parameters?

    There is no need to carry any parameters to query all functions.

  • What is the data format of the response?

    The backend needs to convert List<Brand>the object into JSON formatted data and respond back to the browser. The response data format is as follows:

    [External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-wFHJ9xbV-1659351169455)(../../../../../Chuanzhi Podcast/ 2021/web stage document writing/JavaWeb course documentation/day14-comprehensive case/assets/image-20210825201634849.png)]

The overall process is as follows

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-uoct9gEy-1659351169455)(../../../../../Chuanzhi Podcast/ 2021/web stage document writing/JavaWeb course documentation/day14-comprehensive case/assets/image-20210825200332542.png)]

We first implement the back-end program, and then implement the front-end program.

3.3.1 Backend implementation

3.3.1.1 Dao method implementation

Define abstract methods in com.itheima.mapper.BrandMapperthe interface and use @Selectannotations to write sql statements

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

Since some field names in the table do not correspond to the attribute names in the entity class, you need to define the result mapping in com/itheima/mapper/BrandMapper.xmlthe mapping configuration file and use resultMapthe tag. The content of the mapping configuration file is as follows:

<?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.itheima.mapper.BrandMapper">

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

After defining the result mapping relationship, reference the structure mapping on the interface selectAll()method . Use @ResultMap("brandResultMap")annotations

selectAll()The method of the complete interface is as follows:

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

com.itheima.serviceCreate an interface under the package BrandService, define and query all abstract methods in this interface

public interface BrandService {
    
    

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

And create a package com.itheima.serviceunder impl; implit means that it is a package to put the implementation class of the service layer interface. Under this package create BrandServiceImpla class

public class BrandServiceImpl implements BrandService {
    
    

    @Override
    public List<Brand> selectAll() {
    
    
    }
}

Why define an interface for the service here? Because after the service defines the interface, the object of the Service implementation class can be created in the form of polymorphism in the servlet, as follows:

Polymorphism is used here because it is convenient for us to uncouple Servletand servicedecouple later. From the above code, we can see that SelectAllServletthe class and BrandServiceImplthe class are coupled together. If later BrandServicethere are other better implementation classes (such as called BrandServiceImpl), then the code in SelectAllServletthe class . Later, after we learn Springthe framework , we can SelectAllServletuncouple the class and the code enclosed in the red box. But now we can't do decoupling, here we only need to understand why the interface is defined.

BrandServiceImplThe class code is as follows:

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 mapper = sqlSession.getMapper(BrandMapper.class);

        //4. 调用方法
        List<Brand> brands = mapper.selectAll();

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

        return brands;
    }
}
3.3.1.3 servlet implementation

com.itheima.web.servletUnder the package define SelectAllServleta query named All servlet. The servletlogic is as follows:

  • Call the service selectAll()method to query all brand data, and the interface returns the result
  • Convert the returned result to json data
  • response json data

code show as below:

@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);
    }
}
3.3.1.4 Test backend program

Enter the resource path to access the servlet in the browser http://localhost:8080/brand-case/selectAllServlet. If there is no error and you can see the following information, it means that the back-end program has no problem.

insert image description here

3.3.2 Front-end implementation

The front end needs to send an ajax request after the page is loaded, so the logic of sending the request should be placed in mounted()the hook function. The data returned by the response needs to be assigned to the data model bound by the table. From the figure below, we can see that the data model bound by the table istableData

The front-end code is as follows:

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

     axios({
    
    
         method:"get",
         url:"http://localhost:8080/brand-case/selectAllServlet"
     }).then(function (resp) {
    
    
         _this.tableData = resp.data;
     })
 }

3.4 Add function

The above figure is the dialog box for adding data. After clicking 提交the button the data needs to be submitted to the backend and saved in the database. The following figure is the overall process:

insert image description here

When the page sends a request, the content entered in the input box needs to be submitted to the backend program, and here it is passed in json format. The specific data format is as follows:
insert image description here

Note: Since the data is added, the id in the above json data has no value.

3.4.1 Backend implementation

3.4.1.1 Dao method implementation

Define the add method in BrandMapperthe interface add(), and use @Insertthe annotation to write the sql statement

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

Define the business logic method of adding data in BrandServicethe interfaceadd()

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

Override the method in BrandServiceImplthe class add()and implement the business logic

@Override
public void add(Brand brand) {
    
    
    //2. 获取SqlSession对象
    SqlSession sqlSession = factory.openSession();
    //3. 获取BrandMapper
    BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);

    //4. 调用方法
    mapper.add(brand);
    sqlSession.commit();//提交事务

    //5. 释放资源
    sqlSession.close();
}

Note: Add, delete, and modify operations must submit transactions.

3.4.1.3 servlet implementation

Write a definition named Servlet in com.itheima.web.servletthe package AddServlet. The logic of this servlet is as follows:

  • Receive data submitted by the page. The data submitted by the page is in json format, so here you need to use the input stream to read the data
  • Convert the received data into Brandan object
  • Call add()the method to add business logic processing
  • Add a successful logo to the browser response, here directly respond to the browser with successa string indicating success

The servlet code is implemented as follows:

@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);
    }
}

3.4.2 Front-end implementation

insert image description here

The left side of the picture above is the page effect, and 提交the button can be seen from the right side of the picture above that a click event is bound, and the event is bound to addBrandthe function, so the logic code for adding data should be written in addBrand()the function . In this method, you need to send an asynchronous request and pass the data entered in the form as parameters. as follows

// 添加数据
addBrand() {
    
    
    var _this = this;

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

thenThe anonymous function in the function is a callback function after success, and resp.datathe data returned by the response can be obtained. If the value is , successit means that the data is added successfully. After success, we need to do some logic processing:

  1. Close the Add dialog window

    The dialog box code for adding data is shown in the figure below. From the code, you can see that the dialog box is bound to a dialogVisibledata model. You only need to set the value of the data model to false to close the new dialog window.

  2. requery data

    Whether the data is added successfully or not, as long as the user can view the data on the page, the addition is successful. Here, it is necessary to resend the asynchronous request to obtain all brand data, and this code has been implemented in 查询所有the function , so we can extract this function code and extract it into a selectAll()function

    // 查询所有数据
    selectAll(){
          
          
        var _this = this;
    
        axios({
          
          
            method:"get",
            url:"http://localhost:8080/brand-case/selectAllServlet"
        }).then(function (resp) {
          
          
            _this.tableData = resp.data;
        })
    }
    

    Then you need to improve the code in mounted()the hook function to

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

    At the same time, call in the callback of the new response selectAll()to re-query the data.

  3. A pop-up message reminds the user that the addition is successful

insert image description here

The left side of the picture above is the success prompt code provided by the elementUI official website, while the right side of the picture above is the specific effect.

Note: The this above needs to represent the this of the VUE object.

To sum up, the front-end code is as follows:

// 添加数据
addBrand() {
    
    
    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'
            });
        }
    })
}

s;

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

}


在 `then` 函数中的匿名函数是成功后的回调函数,而 `resp.data` 就可以获取到响应回来的数据,如果值是 `success` 表示数据添加成功。成功后我们需要做一下逻辑处理:

1. **关闭新增对话框窗口**

   如下图所示是添加数据的对话框代码,从代码中可以看到此对话框绑定了 `dialogVisible` 数据模型,只需要将该数据模型的值设置为 false,就可以关闭新增对话框窗口了。

   <img src="../../../../../传智播客/2021年/web阶段文档编写/JavaWeb课程文档/day14-综合案例/assets/image-20210825223933953.png" alt="image-20210825223933953" style="zoom:70%;" />

2. **重新查询数据**

   数据添加成功与否,用户只要能在页面上查看到数据说明添加成功。而此处需要重新发送异步请求获取所有的品牌数据,而这段代码在 `查询所有` 功能中已经实现,所以我们可以将此功能代码进行抽取,抽取到一个 `selectAll()` 函数中

   ```js
   // 查询所有数据
   selectAll(){
       var _this = this;
   
       axios({
           method:"get",
           url:"http://localhost:8080/brand-case/selectAllServlet"
       }).then(function (resp) {
           _this.tableData = resp.data;
       })
   }

Then you need to improve the code in mounted()the hook function to

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

At the same time, call in the callback of the new response selectAll()to re-query the data.

  1. A pop-up message reminds the user that the addition is successful

    [External link image transfer...(img-bPupratK-1659351169457)]

    The left side of the picture above is the success prompt code provided by the elementUI official website, while the right side of the picture above is the specific effect.

    Note: The this above needs to represent the this of the VUE object.

To sum up, the front-end code is as follows:

// 添加数据
addBrand() {
    
    
    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'
            });
        }
    })
}

The following code is continuously updated...

Guess you like

Origin blog.csdn.net/qq_45821255/article/details/126107603