Vue&Element

1.Vue

1.1 概述

Vue 是一套前端框架,免除原生JavaScript中的DOM操作,简化书写。

我们之前也学习过后端的框架 MybatisMybatis 是用来简化 jdbc 代码编写的;而 VUE 是前端的框架,是用来简化 JavaScript 代码编写的。前一天我们做了一个综合性的案例,里面进行了大量的DOM操作。

学习了 VUE 后,这部分代码我们就不需要再写了。那么 VUE 是如何简化 DOM 书写呢?

**基于MVVM(Model-View-ViewModel)思想,实现数据的双向绑定,将编程的关注点放在数据上。**之前我们是将关注点放在了 DOM 操作上;而要了解 MVVM 思想,必须先聊聊 MVC 思想,如下图就是 MVC 思想图解

C 就是咱们 js 代码,M 就是数据,而 V 是页面上展示的内容。 MVC 思想是没法进行双向绑定的。双向绑定是指当数据模型数据发生变化时,页面展示的会随之发生变化,而如果表单数据发生变化,绑定的模型数据也随之发生变化。接下来我们聊聊 MVVM 思想,如下图是三个组件图解

图中的 Model 就是我们的数据,View 是视图,也就是页面标签,用户可以通过浏览器看到的内容;ModelView 是通过 ViewModel 对象进行双向绑定的,而 ViewModel 对象是 Vue 提供的。

1.2 快速入门

Vue 使用起来是比较简单的,总共分为如下三步:

  1. 新建 HTML 页面,引入 Vue.js文件

    <script src="js/vue.js"></script>
    
  2. 在JS代码区域,创建Vue核心对象,进行数据绑定

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

    创建 Vue 对象时,需要传递一个 js 对象,而该对象中需要如下属性:

    • el : 用来指定哪儿些标签受 Vue 管理。 该属性取值 #app 中的 app 需要是受管理的标签的id属性值
    • data :用来定义数据模型
    • methods :用来定义函数。这个我们在后面就会用到
  3. 编写视图

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

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

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

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

1.3 Vue 指令

**指令:**HTML 标签上带有 v- 前缀的特殊属性,不同指令具有不同含义。例如:v-if,v-for…

常用的指令有:

指令作用
v-bind为HTML标签绑定属性值,如设置 href , css样式等
v-model在表单元素上创建双向数据绑定
v-on为HTML标签绑定事件
v-if条件性的渲染某元素,判定为true时渲染,否则不渲染
v-else
v-else-if
v-show根据条件展示某元素,区别在于切换的是display属性的值
v-for列表渲染,遍历容器的元素或者对象的属性

接下来我们挨个学习这些指令

代码演示

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue demo1</title>
</head>
<body>
<script src="js/vue.js"></script>
<div id="app">
<!--    v-model -->
    <input type="text" v-model="username"/>
    <!--插值表达式-->
    {{username}}
    </br>
    <a v-bind:href = "url">百度一下</a>
    <a :href = "url">百度一下</a>
    <input type="text" v-model="url"/>
    </br>

    <input type="button" value="一个按钮" v-on:click="show()">
    <input type="button" value="还是一个按钮" @click = "show">
    </br>
<!--    v-if 条件不满足,不渲染,连这个div都没有-->
    <div v-if="count==3">v-if</div>
    <div v-else-if="count ==4">v-else-if</div>
    <div v-else>v-else</div>
<!--    <div style="display: none;">v-show</div> v-show 条件不满足不显示-->
    <div v-show="count==3">v-show</div>
<!--    双向绑定数据-->
    <input v-model="count">
    </br>
<!--v-for 循环-->
    <div v-for="addr in addrs">
        {{addr}}
    </div>
    <hr/>
<!--    带索引,相当于Java fori-->
    <div v-for="(addr,i) in addrs">
        {{i+1}}---{{addr}}
    </div>
    <div>
        {{ message }}
    </div>

</div>
<script>
    //1. 创建Vue核心对象
    let app = new Vue({
        el:"#app",
        data(){     // data() 是 ECMAScript 6 版本的新的写法
            return{
                username:"",
                url : "https://www.baidu.com",
                count:2,
                message:"hello",
                addrs:["北京","上海","西安"]
            }
        },

        /*data: function () {
            return {
                username:""
            }
        }*/
        methods:{
            show(){
                alert("点击了")
            }
        },
        //vue 生命周期
        beforeMount(){
            console.log("载入前")
        },
        mounted(){
           console.log("加载完毕")
        }
    })
</script>
</body>
</html>

1.4 案例

**需求:**使用 Vue 简化我们在前一天ajax学完后做的品牌列表数据查询和添加功能

1.4.1 查询所有数据

  1. 在 brand.html 页面引入 vue 的js和axios的js文件

    <script src="js/vue.js"></script>
    <script src="js/axios.js"></script>
    
  2. 创建 Vue 对象

    • 在 Vue 对象中定义模型数据
    • 在钩子函数中发送异步请求,并将响应的数据赋值给数据模型
    <script>
        let app = new Vue({
            el:"#app",
            //返回的数据
            data:{
                brands:[]
            },
            //当页面加载完成
            mounted(){
              console.log("页面加载完成了");
                var _this = this;
                // 页面加载完成后,发送异步请求,查询数据
                axios({
                    method:"get",
                    url:"http://localhost:8080/11VueElement/SelectAllServlet"
                }).then(function (resp) {
                    _this.brands = resp.data;
                    console.log(resp.data)
                });
            }
    
        });
    </script>
    
  3. 修改视图

    • 定义 <div id="app"></div> ,指定该 div 标签受 Vue 管理

    • body 标签中所有的内容拷贝作为上面 div 标签中

    • 删除表格的多余数据行,只留下一个

    • 在表格中的数据行上使用 v-for 指令遍历

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

整体页面代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>使用vue查询品牌数据</title>
</head>
<body>
<script src="js/vue.js"></script>
<script src="js/axios.js"></script>
<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>
    let app = new Vue({
        el:"#app",
        //返回的数据
        data:{
            brands:[]
        },
        //当页面加载完成
        mounted(){
          console.log("页面加载完成了");
            var _this = this;
            // 页面加载完成后,发送异步请求,查询数据
            axios({
                method:"get",
                url:"http://localhost:8080/11VueElement/SelectAllServlet"
            }).then(function (resp) {
                _this.brands = resp.data;
                console.log(resp.data)
            });
        }

    });
</script>
</body>
</html>

1.4.2 添加数据

  1. 在 addBrand.html 页面引入 vue 的js文件

    <script src="js/vue.js"></script>
    <script src="js/axios.js"></script>
    
  2. 创建 Vue 对象

    • 在 Vue 对象中定义模型数据 brand
    • 定义一个 submitForm() 函数,用于给 提交 按钮提供绑定的函数
    • submitForm() 函数中发送 ajax 请求,并将模型数据 brand 作为参数进行传递
    <script>
    
        let app = new Vue({
            el: "#app",
            data: {
                brand: {}
            },
            methods: {
                submitForm() {
                    let _this = this;
                    axios.post("http://localhost:8080/11VueElement/AddServlet",this.brand).then(function (resp) {
                        if(resp.data == "success"){
                            location.href = "http://localhost:8080/11VueElement/brand.html";
                        }
                    })
                    console.log(this.brand)
    
                }
    
            }
        });
    </script>
    
  3. 修改视图

    • 定义 <div id="app"></div> ,指定该 div 标签受 Vue 管理

    • body 标签中所有的内容拷贝作为上面 div 标签中

    • 给每一个表单项标签绑定模型数据。最后这些数据要被封装到 brand 对象中

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

完整前端代码如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue添加品牌</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/vue.js"></script>
<script src="js/axios.js"></script>
<script>

    let app = new Vue({
        el: "#app",
        data: {
            brand: {}
        },
        methods: {
            submitForm() {
                let _this = this;
                axios.post("http://localhost:8080/11VueElement/AddServlet",this.brand).then(function (resp) {
                    if(resp.data == "success"){
                        location.href = "http://localhost:8080/11VueElement/brand.html";
                    }
                })
                console.log(this.brand)

            }

        }
    });
</script>

</body>
</html>

通过上面的优化,前端代码确实简化了不少。但是页面依旧是不怎么好看,那么接下来我们学习 Element,它可以美化页面。

2. Element

Element:是饿了么公司前端开发团队提供的一套基于 Vue 的网站组件库,用于快速构建网页。

Element 提供了很多组件(组成网页的部件)供我们使用。例如 超链接、按钮、图片、表格等等~

Element官网open in new window

2.1 快速入门

  1. 创建页面,并在页面引入Element 的css、js文件 和 Vue.js

    <script src="js/vue.js"></script>
    <!-- 引入样式 -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <!-- 引入组件库 -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
    
  2. 创建Vue核心对象

    <script>
        new Vue({
            el:"#app"
        })
    </script>
    
  3. 官网复制Element组件代码

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

2.2 Element 布局

Element 提供了两种布局方式,分别是:

  • Layout 布局
  • Container 布局容器

2.2.1 Layout 局部

通过基础的 24 分栏,迅速简便地创建布局。也就是默认将一行分为 24 栏,根据页面要求给每一列设置所占的栏数。

显示代码根据需求自定定义页面布局

2.2.2 Container 布局容器

用于布局的容器组件,方便快速搭建页面的基本结构。如下图就是布局容器效果。

如下图是官网提供的 Container 布局容器实例:

3. 综合案例

通过上面ElementUI学习,来做一个综合的页面按钮,如下图效果

要完成该页面,我们需要先对这个页面进行分析,看页面由哪儿几部分组成,然后到官网进行拷贝并修改。页面总共有如下组成部分

3.1 准备基本页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ElementUI练习</title>
    <!--    导入在线vue-->
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
    <!-- 引入样式 -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <!-- 引入组件库 -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
    <style>
        .el-table .warning-row {
            background: oldlace;
        }

        .el-table .success-row {
            background: #f0f9eb;
        }
    </style>
</head>
<body>
<div id="app">
  
</div>
  
  <script>
    new Vue({
        el: "#app"
    })
</script>
</body>
</html>

2.3.2 完成表格展示

使用 Element 整体的思路就是 复制 + 修改

2.3.2.1 复制

  1. 在左菜单栏找到 Table 表格并点击,右边主体就会定位到表格这一块,找到我们需要的表格效果(如上图),点击 显示代码 就可以看到这个表格的代码了。

    将html标签拷贝到 <div id="app"></div> 中,如下:

    <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>
    
  2. 将css样式拷贝到我们页面的 head 标签中,如下

    <style>
      .el-table .warning-row {
        background: oldlace;
      }
    
      .el-table .success-row {
        background: #f0f9eb;
      }
    </style>
    
  3. 将方法和模型数据拷贝到script标签下的 Vue 对象指定的位置

    <script>
      export default {
        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>
    

    拷贝完成后通过浏览器打开可以看到表格的效果

表格效果出来了,但是显示的表头和数据并不是我们想要的,所以接下来就需要对页面代码进行修改了。

2.3.2.2 修改

  1. 修改表头和数据

    下面是对表格代码进行分析的图解。根据下图说明修改自己的列数和列名

修改完页面后,还需要对绑定的模型数据进行修改,下图是对模型数据进行分析的图解

这样列表数据就算完成了。后面的界面都是如此操作,详细代码如下

2.4 完整代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ElementUI练习</title>
    <!--    导入在线vue-->
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
    <!-- 引入样式 -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <!-- 引入组件库 -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
    <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="onSearchForm">查询</el-button>
        </el-form-item>
    </el-form>

    <!-- 操作按钮-->
    <el-row>
        <el-button type="danger">批量删除</el-button>
        <el-button type="primary" @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="onSubmit">立即创建</el-button>
                <el-button @click="dialogVisible = false">取消</el-button>
            </el-form-item>
        </el-form>
        </span>
    </el-dialog>


    <!--    列表数据-->
    <template>
        <el-table
                :data="tableData"
                style="width: 100%"
                :row-class-name="tableItemStyle"
                @selection-change="itemSelectionChange">
<!--            列表的复选框-->
            <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"
                    align="center"
                    label="企业名称"
            >
            </el-table-column>
            <el-table-column
                    prop="order"
                    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 slot-scope="scope">
                    <el-button @click="itemOnClick(1,scope.row)" type="primary">修改</el-button>
                    <el-button @click="itemOnClick(-1,scope.row)" type="danger">删除</el-button>
                </el-row>

            </el-table-column>
        </el-table>
    </template>
    </br>
<!--    分页工具条-->
    <el-pagination
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
            :current-page="currentPage4"
            :page-sizes="[10, 15, 20, 25]"
            :page-size="100"
            layout="total, sizes, prev, pager, next, jumper"
            :total="400">
    </el-pagination>
</div>
<script>
    let app = new Vue({
        el: "#app",
        methods: {
            //列表样式
            tableItemStyle({row, rowIndex}) {
                if (rowIndex === 1) {
                    return 'warning-row';
                } else if (rowIndex === 3) {
                    return 'success-row';
                }
                return '';
            },
            itemSelectionChange(val) {
                this.multipleSelection = val;
                console.log(this.multipleSelection)
            },
            itemOnClick(type, row) {
                if (type ==1){
                    this.brand  = row
                    this.dialogVisible = true
                }
                console.log(type, row);
            },
            //查询的表单
            onSearchForm() {
                console.log(this.brand);
            },
            handleSizeChange(val) {
                console.log(`每页 ${val}`);
            },
            handleCurrentChange(val) {
                console.log(`当前页: ${val}`);
            },
            onSubmit() {
                console.log('submit!');
                this.dialogVisible = false
                console.log(this.brand);
            }

        }, data() {
            return {
                dialogVisible: false,
                form: {
                    name: '',
                    region: '',
                    date1: '',
                    date2: '',
                    delivery: false,
                    type: [],
                    resource: '',
                    desc: ''
                },
                currentPage4: 4,
                brand: {
                    brandName: '',
                    companyName: '',
                    order: '',
                    status: '',
                },
                //checkbox选中
                multipleSelection: [],
                tableData: [{
                    brandName: '小米',
                    companyName: '小米科技有限公司',
                    order: '100',
                    status: '1',
                }, {
                    brandName: '小米',
                    companyName: '小米科技有限公司',
                    order: '100',
                    status: '1',
                }, {
                    brandName: '小米',
                    companyName: '小米科技有限公司',
                    order: '100',
                    status: '1',
                }, {
                    brandName: '小米',
                    companyName: '小米科技有限公司',
                    order: '100',
                    status: '1',
                }, {
                    brandName: '小米',
                    companyName: '小米科技有限公司',
                    order: '100',
                    status: '1',
                }]
            }
        }

    });
</script>
</body>
</html>
Loading...