Vue2.0学习笔记

ps|本文是前几天在b站上看动力节点学习视频时做的一些笔记,里面的文档、代码是跟着视频敲的

Vue概述

1.什么是Vuejs

Vuejs是一套构建用户界面的框架,它只关注视图层的内容,它是前端的主流框架之一。

前端3大主流框架:

  • Angular.js
  • React.js
  • Vue.js

前端框架主要负责的是MVC中的V的这一层,主要的工作就是和界面打交道,主要是用来对页面中的数据进行处理,以及制作前端页面相关的特效及动画。

2.为什么要学习Vuejs

在实际项目开发中,不论是做前端开发还是后端开发,使用框架技术是最佳的提高效率的方式。

另外使用Vuejs来做前端框架,对于处理数据的方面可以完全的替换掉原有的dom操作的理念(之前我们常用的原生js以及jQuery类库),通过vuejs框架提供的指令,前端开发人员不再关心dom是如何渲染的,可以有更多的时间去关注业务逻辑本身。

Vue.js作为现今最火爆的前端开发框架,学习后可以有效的提高就业的价值。

3.Vuejs版本1和2的区别

Vue.js当今应用最普遍的有两个版本,分别是Vue1.js以及Vue.js。

值得说明的是版本2在版本1的基础上进行了大量的改动,所以二者从概念到语法上有着很大的区别,随着版本2的成熟以及市场的认可,当今市场中对于新项目的开发已经完全偏向于使用版本2。

另外版本3现今是处于测试及预备阶段,所以现在仍然是以Vue2.js为最主流的版本。

4.MVC 和MVVM的区别

在这里插入图片描述

Vuejs基础语法

1.第一个案例HelloWorld

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 引入Vuejs框架 -->
    <script src="../lib/vue-2.4.0.js"></script>
</head>

<body>
    <!-- 在外层标签div中引入id属性值,将来Vuejs会通过该id,找到需要操作的元素 -->
    <!-- 以下Vue实例vm所控制的这个元素区div,就是我们的V -->
    <div id="app">

        <!-- 在前端页面元素的部分,其中的内容我们暂时以插值表达式的形式来呈现 -->
        <!-- 在两对p标签中分别引入了插值表达式,相当于将p标签对中的内容写活了,内容以变量的形式存在 -->
        <p>{{str1}}</p>
        <p>{{str2}}</p>
    </div>

    <script>

        //当Vuejs框架包导入进来之后,在浏览器缓存中,就已经存在了一个Vue框架的构造函数
        //我们new出来的这个vm对象,就是页面中对于模型和视图(数据和页面元素)的整体调度者
        //通过vm将下方的数据渲染到上方的页面中
        var vm = new Vue({
            el: "#app",      //el元素表现的是要指定为哪个标签进行相应的vuejs的操作
            data: {          //data是vuejs中对于数据的表达,数据约定俗成的都是以json的形式来呈现的
                //data属性中,存放的是el中要使用到的数据
                //这里的data就是MVVM中M,专门用来表现数据的组件
                "str1": "HelloWorld1",
                "str2": "HelloWorld2"
            }
        });
    </script>
</body>

</html>

2.指令属性的基本使用

(1)v-cloak

使用v-cloak主要为了解决插值表达式的闪烁问题

使用插值表达式的问题:

在页面加载的过程中,在页面中的{{}}插值表达式首先会被页面认为是HTML元素中的实实存在的内容。所以浏览器会首先将{{}}展现在页面上,页面加载完成后,插值表达式{{}}才会真正的转变为动态赋予的值。这就造成一种现象,如果将来终端在访问服务器的过程中,网速较慢(网络比较卡),那么我们的{{}}会首先展现出来,{{}}展现出来之后,会一闪而过,最终显示的是最终被赋予的值。这就是前端开发中所谓的,插值表达式的闪烁问题。

<style>
    [v-cloak] {
        display: none;
    }
</style>
<p v-cloak>{{str1}}</p>
(2)v-text、v-html

在Vue.js中,为了页面中的元素渲染值(为前端标签对中的内容赋值)

可以使用3种形式:

  • 插值表达式{{str}}
  • v-text
  • v-html
<body>
    <div id="app">

        <!-- 使用插值表达式为标签对中的内容赋值 -->
        <p>{{str1}}</p>
        <p v-text="str2"></p>
        <p v-html="str3"></p>
    </div>

    <script>

        var vm = new Vue({
            el: "#app",
            data: {
                "str1": "aaaa",
                "str2": "bbbb",
                "str3": "cccc"
            }
        });
    </script>
</body>
(3)插值表达式与v-text/v-html的区别

对于元素已经存在的值,只有插值表达式能够将原有的值保留,在原有的已经存在的值的基础上添加动态数据。

使用v-text和v-html之所以不能够保留元素标签对中原有的内容,是因为在使用以上两个指定属性之前,会提前将标签对中的内容先清空掉,再赋予动态的值。

如果未来的实际项目开发中,需求为在原有的内容的基础上,追加动态的值,我们要选择使用插值表达式。

从另一个方面来看,插值表达式虽然会出现{{}}页面闪烁的现象(v-text和v-html)不会出现页面闪烁的情况,但是对于原有内容的保留,只有插值表达式能够完成,所以插值表达式具有不可替代的优势。

<body>
    <div id="app">

        <!-- 使用插值表达式为标签对中的内容赋值 -->
        <p>-----------{{str1}}-----------</p>
        <p v-text="str2">-----------</p>
        <p v-html="str3">-----------</p>
    </div>

    <script>

        var vm = new Vue({
            el: "#app",
            data: {
                "str1": "aaaa",
                "str2": "bbbb",
                "str3": "cccc"
            }
        });
    </script>
</body>

运行结果:
-----------aaaa-----------

bbbb

cccc

对比v-text和v-html

  • v-text:主要用来赋予内容的,如果赋予到元素中的内容本身包含HTML,那么v-text会将html原封不动的展现在页面上,这些内容是得不到浏览器的解析的。
  • v-html:除了能够为前端元素赋予内容之外,最重要的是,如果内容本身含有html代码,那么赋值后最终展现出来的结果,html元素会得到浏览器的解析的。

从以上结果判断,v-html的功能要更加强大。对于前端页面的展现,不可能让使用该系统的用户看到任何html代码,而是应该让用户看到解析后的html效果。所以在实际项目开发中,使用v-html的概率要高于v-text。

另外使用插值表达式的效果,与v-text是一样的,内容中的html代码是得不到浏览器的解析的。

<body>
    <div id="app">

        <!-- 使用插值表达式为标签对中的内容赋值 -->
        <p>{{str1}}</p>
        <p v-text="str2"></p>
        <p v-html="str3"></p>
    </div>

    <script>

        var vm = new Vue({
            el: "#app",
            data: {
                "str1": "<font color='red'>aaaa</font>",
                "str2": "<font color='red'>bbbb</font>",
                "str3": "<font color='red'>cccc</font>"
            }
        });
    </script>
</body>

运行结果:

<font color=‘red’>aaaa</font>

<font color=‘red’>bbbb</font>

bbbb

(4)v-bind

v-bind:是Vuejs中,提供用于绑定属性的指令

对于v-bind在开发中一共有如下几种使用方式:

  • 直接使用指令属性v-bind:来为元素中的属性进行绑定操作

  • 使用简化后的方式,将v-bind去除,直接使用:来对元素中的属性进行绑定

    因为在实际项目开发中,对于前端元素的绑定是我们常规操作,v-bind的使用复用率非常高,所以每一次都直接写v-bind会很麻烦,所以vuejs为v-bind指令属性提供了简写的方式,直接使用:即可。

    v-bind:title --> :title

    注意:这种简写形式仅仅只是针对于我们的v-bind,以上所讲解的其他的指令是不具备简写形式的。

    在实际项目开发中,我们都是使用这种简写的形式。

  • 在使用v-bind对元素中的属性进行绑定的时候,可以直接在操作值的位置进行内容的拼接。

<body>
    <div id="app">
        <!-- 以下input标签对value属性中的值,使用vm对象,由vm对象将data中的信息动态的赋予到该value属性值当中 -->
        <!-- 
            必须使用指令属性v-bind来完成
            我们需要将v-bind:加在我们需要绑定的属性的前面
         -->
        <input type="text" v-bind:value="str1" />
        <p :title="str2">content...</p>
        <input type="button" value="submit" :title="str3+'Hello World'">
    </div>

    <script>

        var vm = new Vue({
            el: "#app",
            data: {
                "str1": "aaaa",
                "str2": "bbbb",
                "str3": "cccc"
            }
        });
    </script>
</body>

运行结果:

在这里插入图片描述

3.使用v-on指令触发事件

(1)v-on的基本使用

v-on:click="fun1"的形式来绑定事件

相当于原生js中的onclick

v:bind简写为:

v-on简写为@

<body>
    <div id="app">
        <input type="text" :value="str1">

        <input type="button" value="点击1" onclick="fun1()">

        <input type="button" value="点击2" v-on:click="fun2">
        <input type="button" value="点击3" @click="fun3">
    </div>

    <script>
        function fun1() {
            alert("我是1");
        }

        var vm = new Vue({
            el: "#app",
            data: {
                "str1": "aaaa"
            },
            //methods:表示vuejs中对于绑定事件函数的定义,可以同时定义多个函数,多个函数之间使用逗号来进行分隔
            methods: {
                fun2() {
                    alert("我是2");
                },
                fun3() {
                    alert("我是3");
                }
            }
        });
    </script>
</body>
(2)事件修饰符的使用
  • a.stop

    使用.stop来对事件的冒泡机制进行阻止

    js中的事件的冒泡指的是,在触发了内层元素的同时,也会随之继续触发外层元素(外层元素包裹了内层元素)。在点击的过程中,点击了内层元素,也可以认为是同时点击了外层元素。所以两个事件都会触发。

    在实际项目开发中,几乎没有太多需求会使用到这种事件冒泡的机制,所以我们需要阻止事件的冒泡。阻止事件冒泡之后的效果是,在我们点击了内层元素之后,内层元素绑定的事件触发,触发完毕后,由于事件冒泡被阻止,就不会继续触发外层元素的事件了。

    <body>
        <div id="app">
    
            <div style="width: 200px;height: 200px;background-color: red;" @click="fun1">
                <div style="width: 100px; height: 100px;background-color: blue;" @click.stop="fun2">
    
                </div>
            </div>
    
        </div>
    
        <script>
    
            var vm = new Vue({
                el: "#app",
                data: {
                    "str1": "aaaa"
                },
                //methods:表示vuejs中对于绑定事件函数的定义,可以同时定义多个函数,多个函数之间使用逗号来进行分隔
                methods: {
                    fun1() {
                        alert("触发外层div");
                    },
                    fun2() {
                        alert("触发内层div")
                    }
                }
            });
        </script>
    </body>
    
  • b.prevent

    使用.prevent来阻止超链接默认的行为

    所谓默认的行为指的是超链接中的href属性链接

    在实际项目开发中,不仅仅只是按钮需要我们绑定事件来控制行为,超链接的使用我们也是要遵循这种自己绑定事件触发行为的方式。所以在a标签中的href链接往往要被我们以特殊的方式处理掉。

    <body>
        <div id="app">
    
            <!-- 
                前者点击后,先显示弹窗,然后跳转到百度网址
                后者点击后,只显示弹窗
             -->
    
            <a href="https://www.baidu.com" @click="fun1">点击1</a>
            <a href="https://www.baidu.com" @click.prevent="fun1">点击2</a>
    
        </div>
    
        <script>
    
            var vm = new Vue({
                el: "#app",
                data: {
                    "str1": "aaaa"
                },
                //methods:表示vuejs中对于绑定事件函数的定义,可以同时定义多个函数,多个函数之间使用逗号来进行分隔
                methods: {
                    fun1() {
                        alert("点击了");
                    }
                }
            });
        </script>
    </body>
    
  • c.capture

    使用.capture实现捕获触发事件的机制

    使用的是外层div套用内层div的例子(其中内层div没有选择组织冒泡),在此基础上,点击内层的div,先触发内层div的事件,再触发外层div的事件。

    加入了.capture修饰符之后,先触发的是外层的div事件,后触发的是内层div事件。被.capture修改之后,事件优先触发。

    <body>
        <div id="app">
    
            <div style="width: 200px;height: 200px;background-color: red;" @click.capture="fun1">
                <div style="width: 100px; height: 100px;background-color: blue;" @click="fun2">
    
                </div>
            </div>
    
        </div>
    
        <script>
    
            var vm = new Vue({
                el: "#app",
                data: {
                    "str1": "aaaa"
                },
                //methods:表示vuejs中对于绑定事件函数的定义,可以同时定义多个函数,多个函数之间使用逗号来进行分隔
                methods: {
                    fun1() {
                        alert("触发外层div");
                    },
                    fun2() {
                        alert("触发内层div")
                    }
                }
            });
        </script>
    </body>
    
  • d.self

    self实现阻止事件冒泡行为的机制(之前我们讲过了一个.stop)

    使用.self实现的是阻止自身冒泡的行为(它不会真正的阻止冒泡)

    案例:外层div,内层div,在内层div中加入了button

    测试1:在内层div加入.stop修饰符

    观察实验结果,点击最内层的按钮,触发按钮事件,触发了内层的div,外层div没有触发,也就是说,使用.stop修饰符,不会阻止掉自身事件的触发,在自身事件触发完毕之后,阻止事件继续向外扩散。

    测试2:在内层div加入.self修饰符

    观察实验结果,点击按钮,触发按钮事件,没有触发内层div事件,跨过了内层div时间的触发后,继续触发了外层div的事件。

    表示使用.self只是将当前元素(测试中的内层div)的冒泡行为阻止掉了,但是不会影响冒泡行为继续向外扩散(测试中的外层div继续触发了)。

    <body>
        <div id="app">
    
            <div style="width: 200px;height: 200px;background-color: red;" @click="fun1">
                <div style="width: 100px; height: 100px;background-color: blue;" @click.self="fun2">
                    <input type="button" value="点击" @click="fun3">
                </div>
            </div>
    
        </div>
    
        <script>
    
            var vm = new Vue({
                el: "#app",
                data: {
                    "str1": "aaaa"
                },
                //methods:表示vuejs中对于绑定事件函数的定义,可以同时定义多个函数,多个函数之间使用逗号来进行分隔
                methods: {
                    fun1() {
                        alert("触发外层div");
                    },
                    fun2() {
                        alert("触发内层div");
                    },
                    fun3() {
                        alert("点击按钮");
                    }
                }
            });
        </script>
    </body>
    
  • e.once

    使用.once修饰符,只触发一次事件处理函数

    .once需要结合.prevent来使用

    在我们使用事件修饰符的时候,有时候会存在这样的需求,需要同时为@click事件使用多个修饰符。例如我们现在就需要同时使用.once和.prevent修饰符。在使用的同时,通过绑定事件的@click连续的绑定修饰符就可以了。

    语法:@click.prevent.once

    测试:通过超链接的触发来观察

    • 在只使用@click的时候(没有做任何修饰符的修饰),点击超链接,先触发@click,后触发href链接。

    • 在使用@click.prevent的时候,点击超链接,只会触发@click,并不会触发href链接。

    • 当为@click添加@click.prevent.once之后,点击超链接。

      第一次点击:只触发了@click的事件,href链接没有触发。

      第二次点击(已经点击过一次之后再次点击):没有触发@click,只触发了href。

    <body>
        <div id="app">
    
            <a href="https://www.baidu.com" @click="fun1">点击1</a>
            <a href="https://www.baidu.com" @click.prevent="fun1">点击2</a>
            <a href="https://www.baidu.com" @click.prevent.once="fun1">点击3</a>
    
        </div>
    
        <script>
    
            var vm = new Vue({
                el: "#app",
                data: {
                    "str1": "aaaa"
                },
                //methods:表示vuejs中对于绑定事件函数的定义,可以同时定义多个函数,多个函数之间使用逗号来进行分隔
                methods: {
                    fun1() {
                        alert("点击了超链接");
                    }
                }
            });
        </script>
    </body>
    

4.使用v-model指令实现双向数据绑定

单向数据绑定

在这里插入图片描述

我们可以对v-bind的绑定数据的形式得出一个结论,v-bind只能实现数据的单向绑定,从模型(M)绑定到视图(V),使用VM将数据去渲染视图,但是我们无法通过该形式实现数据的双向绑定。

双向数据绑定

在这里插入图片描述

在实际项目开发中,不仅仅只是将模型准确的渲染到视图中,视图中的数据的变化,更需要模型去进行实际的记录。所以我们需要使用双向数据绑定的机制。

v-model的基本使用

使用v-model可以对数据进行双向的绑定操作。

值得注意的是,由于记载页面元素值的需求都是发生在表单元素中,所以v-model只能运用在表单元素中。

form

<input>系列 type:text,hidden,checkbox,radio

<select>

<textarea>
  ...
<body>
    <div id="app">

        <h3>{{str1}}</h3>
        <input type="text" v-model:value="str1">

    </div>

    <script>

        var vm = new Vue({
            el: "#app",
            data: {
                "str1": "aaaa"
            }
        });
    </script>
</body>
使用v-model实现简单的计算器功能
<body>
    <div id="app">

        <input type="text" v-model="num1">

        <select v-model="csign">

            <option value="+">+</option>
            <option value="-">-</option>
            <option value="*">*</option>
            <option value="/">/</option>

        </select>

        <input type="text" v-model="num2">

        <input type="button" value="=" @click="count">

        <input type="text" v-model="result">

    </div>

    <script>

        var vm = new Vue({
            el: "#app",
            data: {
                //设置默认值
                num1: 0,    //键值对的key的引号可加可不加
                num2: 0,
                csign: "+",
                result: 0
            },
            methods: {
                count() {
                    if (this.csign == "+") {

                        //直接取得的数值暂时是不能够直接计算的,默认的情况会按照字符串拼接的形式来触发+符号
                        //默认拼接字符串:1+1=11
                        //在做数学计算之前,需要将数值格式化,才能够计算,使用parseInt方法做数值格式化的操作                    if(this.csign=="+"){
                        this.result = parseInt(this.num1) + parseInt(this.num2);
                    } else if (this.csign == "-") {
                        this.result = parseInt(this.num1) - parseInt(this.num2);

                    } else if (this.csign == "*") {
                        this.result = parseInt(this.num1) * parseInt(this.num2);

                    } else if (this.csign == "/") {
                        this.result = parseInt(this.num1) / parseInt(this.num2);

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

5.使用class样式

使用vuejs控制样式,会使样式变化的操作更加的灵活

class样式的使用

案例1:传递一个class样式的数组,通过v-bind做样式的绑定

该样式与之前的形式没有太大的区别

:class="[样式1,样式2]"

案例2:通过三目(元)运算符操作以上的数组

boolean?true执行:false执行

案例3:使用对象(json)来表达以上三目(元)运算符的操作

{样式:flag}

案例4:以对象引用样式

:class={}

案例5:通过以直接模型M的形式做样式渲染

注意:这样使用必须直接将具体的boolean值结果(true/false)赋值,不能以this.模型的形式来引用

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 引入Vuejs框架 -->
    <script src="../lib/vue-2.4.0.js"></script>

    <style>
        .style1 {
            color: red;
        }

        .style2 {
            background-color: aqua;
        }

        .style3 {
            font-style: italic;
        }

        .style4 {
            font-size: 30px;
        }
    </style>
</head>

<body>
    <div id="app">
        <!-- 传统形式 -->
        <span class="style1 style2 style3 style4">Hello Style</span>
        <br>

        <!-- class样式数组 -->
        <span :class="['style1','style2','style3','style4']">Hello Style</span>
        <br>

        <!-- 使用较少 -->
        <span :class="['style1','style2','style3',flag?'style4':'']">Hello Style</span>
        <br>

        <!-- 使用较多 -->
        <span :class="['style1','style2','style3',{'style4':flag}]">Hello Style</span>
        <br>

        <span :class="{style1:true,style2:fasle,style3:true,style4:flag}">Hello Style</span>


    </div>

    <script>

        var vm = new Vue({
            el: "#app",
            data: {
                flag: false
            }
        });
    </script>
</body>

</html>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 引入Vuejs框架 -->
    <script src="../lib/vue-2.4.0.js"></script>

    <style>
        .style1 {
            color: red;
        }

        .style2 {
            background-color: aqua;
        }

        .style3 {
            font-style: italic;
        }

        .style4 {
            font-size: 30px;
        }
    </style>
</head>

<body>
    <div id="app">

        <span :class="myStyle">Hello Style</span>

    </div>

    <script>

        var vm = new Vue({
            el: "#app",
            data: {
                flag: true,
                //必须是true或false,不能是this.flag
                myStyle: { style1: true, style2: true, style3: true, style4: true }
            }
        });
    </script>
</body>

</html>
style样式补充

在实际项目开发中,对于style样式的使用,没有class使用的广泛(放在style标签中的很多样式),通常style属性仅仅只是对个别指定属性的样式进行的进一步补充使用。

案例1:引用样式对象

:style=“引用样式对象”

注意:在写color这样的样式的属性的时候,由于仅仅只是一个单词,所以不需要加引号,开发中的大多数的样式都是包含横杠( - )的,例如:font-style,background-color等等,在使用这样带有-的样式属性的时候,必须套用在引号中。

‘font-style’

‘background-color’

color

案例2:引用样式对象数组

:style="[样式对象引用1,样式对象引用2]"

<body>
    <div id="app">

        <span :style="myStyle1">Hello Style</span>
        <span :style="[myStyle1,myStyle2]">Hello Style</span>

    </div>

    <script>

        var vm = new Vue({
            el: "#app",
            data: {
                myStyle1: { color: 'red', 'font-size': '30px' },
                myStyle2: { 'font-style': 'italic', 'background-color': 'aqua' }
            }
        });
    </script>
</body>

6.v-for指令和v-if指令的应用

(1)v-for指令的基本使用

案例1:遍历字符串数组

<body>
    <div id="app">

        <!-- 直接使用插值表达式 引用数组 通过下标展现所需元素 -->
        <p>{{cityList[0]}}</p>
        <p>{{cityList[1]}}</p>
        <p>{{cityList[2]}}</p>
        <p>{{cityList[3]}}</p>
        <p>{{cityList[4]}}</p>

        <p v-for="city in cityList">
            {{city}}
        </p>

        <!-- 在以上需求的基础上 遍历出所有的元素以及对应的下标 -->
        <p v-for="(city,i) in cityList">
            {{i}}--------------{{city}}
        </p>

    </div>

    <script>

        var vm = new Vue({
            el: "#app",
            data: {
                cityList: ["北京", "上海", "广州", "深圳", "沈阳"]
            }
        })
    </script>
</body>

案例2:遍历对象数组

<body>
    <div id="app">

        <!-- 每一次遍历出来的元素,代表一个城市信息对象 -->
        <p v-for="(city,i) in cityList">
            <!-- 对象以 .属性名 的形式来取得属性值 -->
            {{i}}----------------{{city.id}}---------------{{city.name}}
        </p>

    </div>

    <script>

        var vm = new Vue({
            el: "#app",
            data: {
                cityList: [
                    { id: "A0001", name: "北京" },
                    { id: "A0002", name: "上海" },
                    { id: "A0003", name: "广州" },
                    { id: "A0004", name: "深圳" },
                    { id: "A0005", name: "沈阳" }
                ]
            }
        })
    </script>
</body>

案例3:遍历对象的属性和属性值

<body>
    <div id="app">

        <!-- 

            遍历对象的属性和属性值:
            必须以取出键值对的形式来遍历
            (value值(属性值),key键(属性名)) in 对象
            (value值(属性值),key键(属性名),i下标) in 对象

         -->
        <p v-for="(value,key,i) in city">
            {{i}}-----------------{{key}}--------------{{value}}
        </p>

    </div>

    <script>

        var vm = new Vue({

            el: "#app",
            data: {
                city: { id: "A0001", name: "北京" }
            }
        })
    </script>
</body>

案例4:遍历整型数字

<body>
    <div id="app">

        <!-- 
            以元素 in 整型数值
         -->
        <p v-for="count in 10">
            {{count}}
        </p>

    </div>

    <script>

        var vm = new Vue({

            el: "#app",
            data: {

            }
        })
    </script>
</body>
(2)v-for指令使用注意事项

对于key属性的使用案例

<body>
    <div id="app">

        <!-- 每一次遍历出来的元素,代表一个城市信息对象 -->
        <p v-for="(city,i) in cityList" :key="city.id">
            <!-- 对象以 .属性名 的形式来取得属性值 -->
            {{i}}----------------{{city.id}}---------------{{city.name}}
        </p>

    </div>

    <script>

        var vm = new Vue({
            el: "#app",
            data: {
                cityList: [
                    { id: "A0001", name: "北京" },
                    { id: "A0002", name: "上海" },
                    { id: "A0003", name: "广州" },
                    { id: "A0004", name: "深圳" },
                    { id: "A0005", name: "沈阳" }
                ]
            }
        })
    </script>
</body>

key属性的作用:

在实际项目开发中,使用v-for仅仅只是将元素遍历出来,并展现在页面中。如果在将来的其他需求中,使用到指定的遍历出来的某个元素,那么视图并没有为我们提供一个有效的辨识指定元素的方式。

所以在遍历元素的过程中,需要为每一条遍历出来的元素做一个有效的标识,这个标识就是就是该元素在页面中的唯一标识,在将来使用到该元素的时候,页面可以通过该标识认准该元素。在v-for的使用过程中,添加key属性及属性值就是做这个标识的最好的手段。

所以我们需要养成一个在遍历元素的过程中,为key属性赋值的好习惯。

对于key属性的应用,值得注意的是:

  • 注意1:key属性值必须是一个数值或者字符串,对象不能当做属性值。否则系统会提出警告,将来不能有效的应用。
  • 注意2:key属性的应用,必须要搭配绑定v-bind指令,在使用的时候必须是以该形式“:key”来使用,否则系统不会生效。
  • 注意3:对key属性所赋的值,必须是记录的唯一标识,我们通常使用的是记录的id。
(3)v-if指令和v-show指令的使用和区别

案例1:v-if的使用

案例2:v-show的使用

<body>
    <div id="app">

        <!-- 

            v-if:boolean true/false
            当值为true,则展现标签对中的信息
            当值为false,则不展现标签对中的信息

         -->

        <p v-if="flag">显示该文本1</p>

        <p v-show="flag">显示该文本2</p>

    </div>![f_show_sam](C:\Users\南山的疆\Desktop\Vue\if_show_same.png)

    <script>

        var vm = new Vue({

            el: "#app",
            data: {
                flag: true
            }
        })
    </script>
</body>

</html>

简单的比较v-if指令和v-show指令,效果是一模一样的。

点击浏览器(F12)中的查看器观察显示页面元素信息

如果flag为true,观察到的结果是一致的

在这里插入图片描述

如果flag为false,观察到的结果是不同的

在这里插入图片描述

其中v-if中的元素是本身就没有的,v-show中的元素是存在的,只是通过false属性值,系统为该元素新增了display:none,表示不展现该元素。

通过观察得到结论:

  • v-if 为true:创建条件元素 为false:去除该元素
  • v-show 为true:展现条件元素 为false:隐藏该元素

在实际项目开发中,一般的需求情况下,我们使用v-if就可以了。但是如果对于元素的展现与否需要频繁的切换,我们需要使用v-show的形式展现或者隐藏元素,因为v-if在每次切换为true的时候都需要重新的创建元素,降低页面展现元素的效率。


综合应用:

​ 完成一个基本信息系统(学生信息管理系统)的查询列表操作,可对该列表进行添加操作,可进行删除操作。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 引入Vuejs框架 -->
    <script src="../lib/vue-2.4.0.js"></script>
    <style>
        .hFontColor {
            color: pink;
        }

        .hAlign {
            text-align: center;
        }

        td {
            text-align: center;
        }
    </style>

</head>

<body>
    <div id="app">

        <!-- 

            模拟表结构:
                student
                id:编号
                name:姓名
                gender:性别
                age:年龄

         -->
        <!-- 
             
            搭建用来填写信息的文本框
            搭建表格结构
            搭建添加信息按钮,删除信息的按钮
            搭建一些基础的样式
        
        -->
        <!-- 

            vuejs建设:
                data:
                    模型
                    对象集合,编号,姓名,性别,年龄
                methods:
                    添加方法,删除方法
                    扩展:查询信息列表方法

         -->

        <h3 :class="hstyle">学生信息管理系统</h3>
        <hr width="100%">
        <br>
        <!-- 搭建添加操作相关信息 -->
        编号:<input type="text" v-model="id">&nbsp;&nbsp;
        姓名:<input type="text" v-model="name">&nbsp;&nbsp;
        性别:<input type="text" v-model="gender">&nbsp;&nbsp;
        年龄:<input type="text" v-model="age">&nbsp;&nbsp;

        <input type="button" value="保存学生" @click="save">

        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        <!-- 

            搜索的方式,可以触发按钮进行搜索,也可以通过如下方式,在触发敲键盘之后,触发搜索的方法

         -->
        搜索:<input type="text" v-model="sname" @keyup="search">

        <!-- <input type="button" value="搜索学生" @click="search"> -->

        <br><br>

        <!-- 搭建表格元素 -->
        <table border="1" width="100%" align="center" cellpadding="6px" cellspacing="0px">
            <tr>
                <td>序号</td>
                <td>编号</td>
                <td>姓名</td>
                <td>性别</td>
                <td>年龄</td>
                <td>操作</td>
            </tr>

            <!-- 内容部分 读取模型SList中的数据,使用v-for的形式对sList做遍历 -->
            <!-- 
                每一个s,就是每一个遍历出来的学生对象,将来在取得学生信息的时候,通过{{s.属性}}来取值
                i变量是遍历出来元素的下标,从0开始做标记,在序号中,应该是以下标+1的方式开始标记(序号从1开始计数)
             -->
            <tr v-for="(s,i) in sList" :key="s.id">
                <td>{{i}}</td>
                <td>{{s.id}}</td>
                <td>{{s.name}}</td>
                <td>{{s.gender}}</td>
                <td>{{s.age}}</td>
                <td>
                    <!-- 

                        使用href="javascript:void(0)"将超链接的href行为禁用掉,该超链接只能以绑定事件的形式来触发行为
                        与之前学习的click的prevent的用处是一样的

                     -->
                    <!-- 

                        根据编号执行删除操作
                        注意:
                            在方法中传递实参,不需要使用插值表达式
                            使用方法:del(s.id)
                            而不是:del({{s.id}})

                      -->

                    <a href="javascript:void(0)" @click="del(s.id)">删除学生</a>
                </td>
            </tr>

        </table>
    </div>

    <script>

        var vm = new Vue({

            el: "#app",
            data: {

                sList: [
                    { id: "A0001", name: "zs", gender: "男", age: "23" },
                    { id: "A0002", name: "ls", gender: "男", age: "24" },
                    { id: "A0003", name: "ww", gender: "男", age: "25" }
                ],
                searchList: [
                    { id: "A0001", name: "zs", gender: "男", age: "23" },
                    { id: "A0002", name: "ls", gender: "男", age: "24" },
                    { id: "A0003", name: "ww", gender: "男", age: "25" }
                ],

                id: "",
                name: "",
                gender: "",
                age: "",
                sname: "",
                hstyle: { hFontColor: true, hAlign: true }
            },
            methods: {

                save() {
                    /*
                        通过在页面中对文本框进行信息的完善(对视图V进行数据的填充)
                        根据使用对于视图中值的绑定方式是v-model的方式,会实现双向数据绑定
                        通过对视图的数据的填充,同时也是对模型中数据的填充
                        在我们触发的save方法当中,取得模型中的值,就相当于是取得了在页面文本框填充的数据
                        将这些数据收集起来,形成一个对象,将该对象添加到我们的sList对象数据中就可以了
                    */

                    var s = { id: this.id, name: this.name, gender: this.gender, age: this.age };

                    this.sList.push(s);
                },

                del(id) {
                    //id:需要删除记录的id,根据id来进行删除

                    /*
                        遍历sList中所有的对象
                        从每一个对象中取得id信息,将每一个id与参数id进行比较
                        如果id值相等,证明我们找到了需要删除的记录
                        将该记录从sList中移除掉
                    */

                    for (var i = 0; i < this.sList.length; i++) {

                        //如果id值相等,证明我们找到了需要删除的记录
                        if (this.sList[i].id == id) {

                            //如果id值相等,证明我们找到了需要删除的记录
                            this.sList.splice(i, 1);
                        }
                    }

                },

                search() {
                    /*

                        将sList备份searchList
                        将sList清空掉(等待搜索出来的对象,对sList进行重新的装配过程)

                        遍历searchList,取得每一个对象,根据对象取得名字
                        如果名字包含输入的关键字,则证明该对象已经搜索到了,将该对象装配到sList中
                        最终展现的信息是最新经过搜索后的sList

                        注意:
                            一定要先将sList进行备份,使用其他的对象数组时不能够展现信息的,
                            因为v-for循环当中已经写好了,需要遍历的就是sList

                    */

                    //用来遍历对象信息用的
                    /*
                        我们刚才所使用的备份数据的方式,searchList是在方法中声明的局部变量
                        该变量是在触发当前方法的时候,为sList做备份
                        例如:
                            经过搜索s关键字之后,sList中经过重新装配的对象有zs和ls
                            当再一次进行搜索,再一次触发该方法的时候,为searchList备份的sList,就只能备份zs和ls这两个对象了
                            所以造成的结果,是数据越来越少,能够搜索到的有效的数据的范围,仅仅只是在上一次搜索后产生的对象数组
                        对于备份的信息,一定要写成模型,而且备份的方式,是完全copy需要备份的信息
                    */
                    //var searchList = this.sList;

                    //用来装配新对象用的
                    this.sList = [];

                    /*

                        使用indexOf方法做判断
                        如果判断结果大于等于0,则说明该名称是有效的搜索项

                    */
                    for (var i = 0; i < this.searchList.length; i++) {

                        if (this.searchList[i].name.indexOf(this.sname) >= 0) {

                            //将搜索到的有效的对象,重新装配到sList中
                            this.sList.push(this.searchList[i]);
                        }
                    }
                }

            }
        })
    </script>
</body>

</html>

过滤器

过滤器是一个通过输入数据,能够及时对数据进行处理并返回一个数据结果的简单的函数 。

在实际项目开发中根据实际的需求,可以自己编写所需要的过滤器。

过滤器经常用在数据所需的格式化时使用:

例如:

​ 字符串的格式化

​ 以及日期时间的格式化等等

过滤器的最大的作用就是体现其复用性,如果我们在前端处理的某些文本信息每一次都需要经过重复的特殊处理,那么我们一定是要编写一个过滤器来使用。

在这里插入图片描述

1.全局过滤器的使用

全局过滤器指的是所有vm对象都能共享使用的过滤器。

过滤器能够使用在两个地方:

​ (mustache)插值表达式/指令(bind属性)

过滤器的语法:使用管道符“|”

过滤器在插值表达式中的使用

案例1:将所有的字母变为大写

<body>

    <div id="app">

        <!-- 

            使用过滤器的语法:
                {{内容 | 过滤器}}

         -->
        <p>{{str1 | ucase}}</p>
    </div>

    <script>

        //自定义全局过滤器
        /*
            语法:Vue.filter
            参数1:为该过滤器命名
            参数2:函数,指定过滤器的行为
                    函数参数:我们需要操作的数据
        */
        Vue.filter("ucase", function (value) {
            //通过value的形参取得了需要操作的值(aaa)
            //将值处理为大写字母
            value = value.toUpperCase();
            return value;
        })

        var vm = new Vue({
            el: "#app",
            data: {
                "str1": "aaa"
            }
        })

    </script>
</body>

案例2:定义格式化时间的全局过滤器

<body>

    <div id="app">

        <p>{{currentTime | dateTimeManager}}</p>
    </div>

    <script>

        Vue.filter("dateTimeManager", function (dateTime) {

            //取得日期时间的具体值
            //将年月日时分秒分别取出,格式化为 2021-04-16 10:10:10
            //2021-04-16 10:10:10   19为字符串 char(19)
            var y = dateTime.getFullYear();

            //不足两位在前面补0
            var M = (dateTime.getMonth() + 1 + "").toString().padStart(2, "0");
            var d = dateTime.getDate().toString().padStart(2, "0");

            var h = dateTime.getHours().toString().padStart(2, "0");
            var m = dateTime.getMinutes().toString().padStart(2, "0");
            var s = dateTime.getSeconds().toString().padStart(2, "0");

            //在ES5中,我们必须以使用+(拼接符)的形式来对字符串进行拼接的操作
            //return y + "-" + m + "-" + d;

            //在ES6中,仅仅只使用反引号 "`" 来解决复杂的字符串拼接的工作
            return `${y}-${M}-${d} ${h}:${m}:${s}`;
        })

        var vm = new Vue({
            el: "#app",
            data: {
                "currentTime": new Date()
            }
        })

    </script>
</body>

过滤器在v-for中的使用

案例:将所有商品进行打折(打8折,5折…)

<body>

    <div id="app">

        <p v-for="f in fruitList" :key="f.id">
            {{f.name}}-----------------{{f.price | disCount5}}
        </p>

    </div>

    <script>

        Vue.filter("disCount8", function (value) {

            return parseInt(value) * 0.8;

        })

        Vue.filter("disCount5", function (value) {

            return parseInt(value) * 0.5;

        })

        var vm = new Vue({
            el: "#app",
            data: {
                "fruitList": [
                    { "id": "A0001", "name": "苹果", "price": 10 },
                    { "id": "A0002", "name": "菠萝", "price": 15 },
                    { "id": "A0003", "name": "桃子", "price": 8 }
                ]
            }
        })

    </script>
</body>

以上的案例,我们都是使用在了插值表达式当中,除了使用在插值表达式中之外,我们的过滤器还可以使用在bind属性指令当中,该形式没有插值表达式使用的广泛。

可以连续使用多个过滤器

<body>

    <div id="app">

        <!-- 

            连续使用多个管道符来连接多个过滤器
            {{str1 | 过滤器1 | 过滤器2 | ...n}}

         -->
        <p>{{str1 | filter1 | filter2}}</p>

    </div>

    <script>

        //过滤器1:将小写字母变成大写
        Vue.filter("filter1", function (value) {

            return value.toUpperCase();

        })

        //过滤器2:在原有字符串的基础上,最后增加字符串123
        Vue.filter("filter2", function (value) {

            return value + "123";

        })

        var vm = new Vue({
            el: "#app",
            data: {
                "str1": "aaa"
            }
        })

    </script>
</body>

2.私有过滤器的使用

私有过滤器指的是在指定的vm对象中来定义过滤器,该过滤器只在当前的vm对象中会发挥作用,其他的vm对象不能使用的。

语法:在vm对象中指定过滤器相关的属性和属性值

vm

​ filters:{

​ filter1

​ filter2

​ …

​ }

<body>

    <div id="app1">

        <p>{{str1 | filter1 | filter3}}</p>

    </div>

    <br>

    <div id="app2">

        <p>{{str1 | filter1 | filter3}}</p>

    </div>

    <script>

        //过滤器1:将小写字母变成大写
        Vue.filter("filter1", function (value) {

            return value.toUpperCase();

        })

        //过滤器2:在原有字符串的基础上,最后增加字符串123
        Vue.filter("filter2", function (value) {

            return value + "123";

        })

        var vm1 = new Vue({
            el: "#app1",
            data: {
                "str1": "aaa"
            },
            filters: {
                filter3: function (value) {
                    return value + "bbb";
                }
            }
        })

        var vm2 = new Vue({
            el: "#app2",
            data: {
                "str1": "aaa"
            }
        })

    </script>
</body>

执行结果:
AAAbbb


AAA

如果全局过滤器和私有过滤器的命名是一样的,那么默认使用的是私有过滤器。

系统在使用过滤器的时候,根据名称去找相应的过滤器,先找私有过滤器,如果没有私有的,则继续通过该名称寻找全局过滤器。

这种方式也被称之为就近原则(优先使用的是范围窄的)

<body>

    <div id="app">

        <p>{{str1 | filter2}}</p>

    </div>

    <script>

        //过滤器1:将小写字母变成大写
        Vue.filter("filter1", function (value) {

            return value.toUpperCase();

        })

        //过滤器2:在原有字符串的基础上,最后增加字符串123
        Vue.filter("filter2", function (value) {

            return value + "123";

        })

        var vm = new Vue({
            el: "#app",
            data: {
                "str1": "aaa"
            },
            filters: {
                filter2: function (value) {
                    return value + "bbb";
                }
            }
        })

    </script>
</body>

执行结果:
aaabbb

全局过滤器器和私有过滤器能够搭配起来一起使用的

<body>

    <div id="app">

        <p>{{str1 | filter1 | filter2 | filter3}}</p>

        <p>{{str1 | filter3 | filter2 | filter1}}</p>

    </div>

    <script>

        //过滤器1:将小写字母变成大写
        Vue.filter("filter1", function (value) {

            return value.toUpperCase();

        })

        //过滤器2:在原有字符串的基础上,最后增加字符串123
        Vue.filter("filter2", function (value) {

            return value + "123";

        })

        var vm = new Vue({
            el: "#app",
            data: {
                "str1": "aaa"
            },
            filters: {
                filter3: function (value) {
                    return value + "bbb";
                }
            }
        })

    </script>
</body>

如果是按照123的顺序

<p>{{str1 | filter1 | filter2 | filter3}}</p>

执行结果为:AAA123bbb

如果是按照321的顺序

<p>{{str1 | filter3 | filter2 | filter1}}</p>

执行结果为:AAABBB123

通过以上测试结果,观察得到以下结论

过滤器的使用:

​ 可以同时使用多个过滤器,这多个过滤器在一起使用的时候,是具有信息传递性的。先处理排在前面的过滤器,得到结果传递到下一个过滤器中继续进行后续处理。

指令

1.自定义全局指令

指令与属性相似,是对指定元素样式或行为赋予。

我们可以在实际项目开发中自定义一些我们所需的指令来有效的管理元素。

在页面中自定义的全局指令,可以为每一个vm对象中的元素提供服务,只要vm中的标签引用了全局指令那么一定会即时生效,一般情况下我们普遍做的都是自定义全局指令来管理元素。

值得一提的是自定义指令需要经常搭配vuejs中的钩子函数来进行操作。

自定义全局指令的语法:

​ Vue.directive()

案例1:自定义一个全局指令让文本框自动获得焦点

<body>

    <div id="app">

        <!-- 

            请使用自定义全局指定来操控该元素的样式,让文本框中输入的信息改变颜色

         -->
        请输入信息:<input type="text" v-dt1>

    </div>

    <script>

        //自定义全局指令
        /*

            directive提供两个参数
            参数1:关于指令的名称,在定义的时候前面不需要加"v-"前缀,但是在使用的过程中一定要加"v-"前缀
                例如我们现在为自定义指令取的名字叫做dt1(不加v-),那么在将来的元素中使用的时候,就是使用v-dt1(加上v-)
            参数2:json对象,在这个对象身上,有一些指令相关的函数,这些函数可以在特定的阶段,执行相关的操作(钩子函数)

        */
        Vue.directive("dt1", {

            /*
            
                以下定义了3个函数,这3个函数是与vuejs对象生命周期密切相关的函数
                在每个函数中,第一个参数el(表示element),表示的是指令操作的元素
                注意:每一个el对象,同时也是一个原生js对象(dom对象)

                在未来的实际项目开发中:
                    使用bind函数来操作元素的样式(css)
                    使用inserted函数来操作元素的行为(js)
            
            */

            //bind函数:每当执行绑定到该元素上的时候,会立即执行这个bind函数,该函数只执行一次
            bind: function (el) {

                //将指定元素的文本信息改变颜色
                //执行结果:文本框中的信息变红
                //el.style.color = "red";

                //页面加载完毕后,让指定的文本框自动获取焦点
                /*

                    执行结果:文本框并没有自动取得焦点
                    在元素刚绑定了指令的时候,还没有插入到dom中去,这时候调用focus方法一定是没有作用的
                    一个元素,只有插入dom之后,才能够触发dom相关的方法(例如使用focus方法取得焦点)

                */
                // el.focus();
            },

            //inserted函数:表示元素插入到dom中的时候,会执行该函数,该函数只会执行一次
            inserted: function (el) {

                //执行结果:文本框成功的自动取得焦点了
                el.focus();
            },

            //updated函数:当vuejs中的元素更新的时候,会触发该函数,元素是可以随时进行更新的,所以该函数也可以触发多次
            updated: function (el) {

                //对于当前指令相关的测试,该函数暂时先用不到
            }
        })

        var vm = new Vue({
            el: "#app",
            data: {
                "str1": "aaa"
            }
        })

    </script>
</body>

案例2:通过参数为指令进行赋值

<body>

    <div id="app">

        <!-- 

            请使用自定义全局指定来操控该元素的样式,让文本框中输入的信息改变颜色

         -->
        请输入信息:<input type="text" v-dt1="'red'">

    </div>

    <script>

        Vue.directive("dt1", {

            //bind函数:每当执行绑定到该元素上的时候,会立即执行这个bind函数,该函数只执行一次
            /*
            
                参数2:是在元素使用指令的时候,为函数传递的一个具体的值,该参数来接收该值,通过赋值的形式为元素来进行操作
            */
            bind: function (el, binding) {

                //执行结果:文本框的信息会随着传递的参数值的变化而变化
                el.style.color = binding.value;

            }
        })

        var vm = new Vue({
            el: "#app",
            data: {
                "str1": "aaa"
            }
        })

    </script>
</body>

2.自定义私有指令

私有指令是指定义在指定的vm对象中,只针对当前vm对象描述的元素生效的指令。其他的vm对象中的元素,是不能够使用该指令的。

语法:

vm

​ directives:{

​ 指令1…

​ 指令2…

​ }

<body>

    <div id="app1">

        <!-- 

            使用私有指令与全局指令是一样的,都是以v-指令的形式来写

         -->
        <p v-dt1>全局——显示信息1</p>
        <p v-mydt>局部——显示信息1</p>

    </div>

    <div id="app2">

        <p v-dt1>全局——显示信息2</p>
        <p v-mydt>局部——显示信息2</p>

    </div>

    <script>

        Vue.directive("dt1", {

            bind: function (el, binding) {

                //执行结果:文本框的信息会随着传递的参数值的变化而变化
                el.style.color = "green";

            }
        })

        var vm1 = new Vue({
            el: "#app1",
            data: {
                "str1": "aaa"
            },
            directives: {
                "mydt": {
                    bind: function (el) {
                        el.style.color = "red";
                    }
                }
            }
        })

        var vm2 = new Vue({
            el: "#app2",
            data: {
                "str1": "aaa"
            }
        })

    </script>
</body>

vuejs对象的生命周期

1.生命周期简介

生命周期是指Vuejs对象从创建到销毁的全过程。

生命周期1:创建阶段

在这里插入图片描述

  1. new Vue():执行代码var vm = new Vue({}),表示创建一个Vue对象(实例)。

  2. Init(Events&Lifecycle):执行完以上代码后步入到对象初始化的前期阶段,表示通过以上代码我们创建了Vuejs对象,此时,在新建的对象身上,具备了一些生命周期相关的函数(生命周期的钩子函数)和默认的事件,但是其他的相关的组件还没有被创建(data、methods、filter等等都没有被创建出来)。

    执行Init(Events&Lifecycle)之后,钩子函数都被创建出来,马上调用生命周期函数beforeCreate,在该函数执行的时候,我们最常使用的组件data和methods等,都没有被创建出来。

  3. Init(injection&reactivity):该阶段是对象初始化的后期阶段。执行Init(injectioins&reactivity)的方式是调用生命周期函数created。在该函数中,data和methods都已经被初始化好了。

    也就是说,如果要使用methods中的方法,或者是操作data中的数据,最早可以在created方法中来进行操作。

在这里插入图片描述

  1. Init对象初始化阶段执行完毕后,通过对元素以及模板进行判断,系统开始编辑模板,将Vue代码中的指令进行执行,然后在内存中生成一个编辑好的模板字符串,最终将该模板字符串渲染为内存中的DOM。

    但是此时仅仅只是在内存中渲染好了模板,并没有将模板挂载到页面中去。将阶段执行完毕后,执行beforeMount方法。

  2. Create vm:该阶段是将内存中编译好的模板,替换到浏览器的页面中。该阶段执行完毕后,执行mounted方法。只要执行完了mounted方法,就表示整个Vue对象已经初始化完毕了,此时正式脱离创建阶段进入到运行阶段。如果要通过某些插件操作页面上的DOM节点,最早是要在mounted中进行。

生命周期2:对象运行阶段

在这里插入图片描述

  1. Virtual DOM:该阶段会根据data中的最新数据,重新渲染出一份最新的DOM树,当最新的内存DOM树被更新了之后,会把最新的DOM树重新渲染到页面中去,这时候就完成了使用模型Model去渲染视图View的过程。

    该阶段的执行会使用到两个函数beforeUpdate和updated,这两个函数会根据data数据的变化,可重复的执行多次。

    当beforeUpdate方法执行的时候,页面中的显示还是以前的数据,但是data中保存中的是更新后的新数据,页面此时还没有和最新的数据保持同步。

    updated函数执行的时候,页面和data数据已经保持同步了,都是最新的数据了。

生命周期3:对象销毁阶段

在这里插入图片描述

  1. Teardown(拆卸),该阶段为对象销毁的阶段,当对象实例运行完毕后,如果达到了对象销毁的条件,执行beforeDestroy函数,该函数的执行正式标志着对象从运行阶段进入到了销毁的阶段。

    当beforeDestroy函数执行的时候,对象身上所有的组件data、methods、filter、directive等组件都还处于可用状态(因为对象只是步入到了销毁的阶段,还没有销毁),该函数执行完毕后,对象正式销毁。

  2. Destroyed:该阶段为对象销毁后的阶段。该阶段会执行destroyed函数,当该函数执行的时候,对象已经被销毁了,里面的data、methods等相应的组件也不能使用了。

以上生命周期中使用的所有的函数,就是Vuejs生命周期中最重要的钩子函数。

2.Vuejs生命周期中的钩子函数解析

  • beforeCreate

  • created

  • beforeMount

  • mounted

  • beforeUpdate

  • updated

  • beforeDestroy

  • destroyed

<body>

    <div id="app">

        <!-- 

            测试对象创建相关的钩子函数

         -->
        <span id="msg">{{str1}}</span>

        <br>
        <!-- 

            测试对象运行相关的钩子函数

         -->
        请输入信息:<input type="text" v-model="str1">

    </div>

    <script>

        var vm1 = new Vue({
            el: "#app",
            data: {
                "str1": "aaa"
            },
            methods: {
                showInfo() {
                    alert(this.str1 + "bbb");
                }
            },

            //这是我们Vuejs对象生命周期第一个钩子函数,表示实例在完全被创建出来之前,会执行该函数
            //注意:beforeCreate函数执行的时候,data和methods中的数据都没有被初始化出来
            beforeCreate() {

                //结果:undefined,表示data中的数据没有被初始化
                // alert(this.str1);

                //结果:没有执行该函数,表示methods中的函数没有被初始化
                // this.showInfo();
            },

            //在created中,data和methods等组件都已经被初始化完毕了(注意:此时还没有编辑模板)
            //如果我们需要使用data中的数据,或者使用methods中的方法,最早只能在created方法中进行操作
            created() {

                //aaa:说明在此方法中已经能够使用data的数据了
                // alert(this.str1);

                //aaabbb:说明此方法中已经能够使用methods中的方法
                // this.showInfo();
            },

            //该函数的执行,表示模板已经在内存中编辑成功了,但是还没有将模板渲染到页面中
            beforeMount() {
                //弹出{{str1}},证明此时还没有将模板渲染到页面中
                //在beforeMount执行的时候,页面中的元素还没有被真正的替换成我们所需的值,只是在内存中写了一些模板字符串
                // var msg = document.getElementById("msg").innerHTML;
                // alert(msg);
            },

            //该函数表示内存中的模板,已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了
            //mounted函数时Vuejs对象创建期间的最后一个生命周期函数,当我们执行完mounted方法之后表示实例已经被完全创建好了
            mounted() {

                // var msg = document.getElementById("msg").innerHTML;
                //aaa:证明内存中的模板已经同步到了页面中
                // alert(msg);
            },

            //以下测试对象运行中的两个函数
            //在更新数据前,执行beforeUpdate函数
            //执行该函数的时候,页面中显示的还是上一次的旧数据,此时data中的数据是最新的,页面尚未和最新的data中的数据保持同步
            beforeUpdate() {

                // var msg = document.getElementById("msg").innerHTML;
                //每一次展现的数据都是上一次的旧数据
                // alert(msg);
            },

            //执行该函数的时候,页面和data数据已经保持同步了,都是最新的数据了
            updated() {

                var msg = document.getElementById("msg").innerHTML;
                //展现的是最新的data中的数据
                alert(msg);
            },

            //执行该函数说明对象处于准备销毁阶段,对象中的组件(data、methods)在此函数中是仍然可以使用的
            beforeDestroy() {

            },

            //执行该函数说明对象已经销毁完毕了,对象中的组件(data、methods)随着对象的销毁也不可用了
            destroyed() {

            }
        })

    </script>
</body>

Vuejs的ajax请求

Vuejs本身不支持发送ajax请求的,需要使用插件来实现。

vue-resource插件、axios插件

1.Vuejs生命周期中的钩子函数解析

使用vue-resource插件来实现get和post请求

vuejs将请求发送到后台,后台进行请求处理

后台(java、Node.js…)

使用get请求和post请求的区别:

get请求:

//对于get请求,必须是在路径的后面以url?key1=value&key2=value2这种传统的形式来传递参数
this.$http.get("myServlet01.do?name=ls").then(function (data) {})

post请求:

//post请求参数传递的方式,是以请求的方式来传递的,所以不能将参数挂在URL后面
/*
    关于post请求传递参数的问题:
    手动发起的post请求,默认没有表单格式,所以有些服务器就处理不了
    我们需要通过post方法的第三个参数,{emulateJSON:true}设置,提交的内容类型就设置为了普通表单的格式传递参数
*/
this.$http.post("myServlet02.do",{"name":"hello"},{emulateJSON:true}).then(function (data) {})

案例:获得后台传递的学生信息

Student.java:

public class Student {
    private String id;
    private String name;
    private String age;
    //构造方法、get/set方法
}

Servlet类(get请求):

@WebServlet("/myServlet01.do")
public class MyServlet01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入到doGet方法,处理get请求");

        String name = req.getParameter("name");
        System.out.println(name);

        Student s = new Student("A0001","zs","23");

        //将s对象解析为json串,返回到前端
        //{"age":"23","id":"A0001","name":"zs"}

        JSONObject object = JSONObject.fromObject(s);

        resp.setContentType("application/json;charset=utf-8");
        PrintWriter writer = resp.getWriter();
        writer.println(object);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入到doPost方法,处理post请求");
    }
}

get.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>mytitle</title>
    <%--

      导入vue-resource类库之后,就可以使用this.$http.xxx来实现ajax功能了

      注意:对于idea,直接复制粘贴过来的文件有可能报404错误(资源定位不到的)
        这时我们可以先手动创建这个文件,再复制粘贴里面的内容到该文件中就可以了

    --%>
    <script src="vue/vue-2.4.0.js"></script>
    <script src="vue/vue-resource-1.3.4.js"></script>
  </head>
  <body>
    <div id="app">
      <button @click="getStudent">点击取得学生信息</button>
      <br><br>
      编号:<span>{{id}}</span><br>
      姓名:<span>{{name}}</span><br>
      年龄:<span>{{age}}</span><br>

    </div>
    <script>

      var vm = new Vue({
        el:"#app",
        data:{
          "id":"",
          "name":"",
          "age":""
        },
        methods:{
          getStudent(){

            //发出ajax请求,取得学生信息,在页面中局部刷新学生信息
            //this.$http.get("请求路径",请求参数,then(回调函数))
            //对于参数的传递,get请求和post请求的参数传递的语法是不同的,这一点有别于其他的前端语言
            //对于get请求,必须是在路径的后面以url?key1=value&key2=value2这种传统的形式来传递参数

            this.$http.get("myServlet01.do?name=ls").then(function (data) {

              //通过data.body的形式来拿到服务器返回的数据
              //为页面填写值
              /*this.id = data.body.id;
              this.name = data.body.name;
              this.age = data.body.age;*/

              data = data.body;
              this.id = data.id;
              this.name = data.name;
              this.age = data.age;
            })
          }
        }
      })
    </script>
  </body>
</html>

Servlet类(post请求):

@WebServlet("/myServlet02.do")
public class MyServlet02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {


    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入到doPost方法,处理post请求");

        String name = req.getParameter("name");
        System.out.println(name);

        Student s = new Student("A0002","ls","23");

        //将s对象解析为json串,返回到前端
        //{"age":"23","id":"A0001","name":"zs"}

        JSONObject object = JSONObject.fromObject(s);

        resp.setContentType("application/json;charset=utf-8");
        PrintWriter writer = resp.getWriter();
        writer.println(object);
    }
}

post.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>mytitle</title>
    <%--

      导入vue-resource类库之后,就可以使用this.$http.xxx来实现ajax功能了

      注意:对于idea,直接复制粘贴过来的文件有可能报404错误(资源定位不到的)
        这时我们可以先手动创建这个文件,再复制粘贴里面的内容到该文件中就可以了

    --%>
    <script src="vue/vue-2.4.0.js"></script>
    <script src="vue/vue-resource-1.3.4.js"></script>
  </head>
  <body>
    <div id="app">
      <button @click="getStudent">点击取得学生信息</button>
      <br><br>
      编号:<span>{{id}}</span><br>
      姓名:<span>{{name}}</span><br>
      年龄:<span>{{age}}</span><br>

    </div>
    <script>

      var vm = new Vue({
        el:"#app",
        data:{
          "id":"",
          "name":"",
          "age":""
        },
        methods:{
          getStudent(){

            //发出ajax请求,取得学生信息,在页面中局部刷新学生信息
            //发出post请求
            //post请求参数传递的方式,是以请求的方式来传递的,所以不能将参数挂在URL后面

            /*

              关于post请求传递参数的问题:
                手动发起的post请求,默认没有表单格式,所以有些服务器就处理不了
                我们需要通过post方法的第三个参数,{emulateJSON:true}设置,提交的内容类型就设置为了普通表单的格式传递参数
             */

            this.$http.post("myServlet02.do",{"name":"hello"},{emulateJSON:true}).then(function (data) {

              //与get请求一样,我们接收到后台响应的信息,需要先使用data.body进行处理,才能够拿到我们需要的数据
              data = data.body;
              this.id = data.id;
              this.name = data.name;
              this.age = data.age;

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

使用axio插件来实现ajax的get和post请求

axios插件的两种使用方式

第一种使用方式:

axios({

	method:"get/post"

})

get请求(三种方式):

第一种:不能直接使用this.xx,需要将指向vue对象的this赋值给外部方式定义的属性,然后在内部方法中使用该属性。

getStudent() {

    var _this = this;

    axios({

        method:"get", //请求方式
        url:"myServlet03.do"  //请求路径
            
    }).then(function (result) {
        _this.id = result.data.id;
        _this.name = result.data.name;
        _this.age = result.data.age;
    })

}

第二种:使用箭头表达式=>代替原有的function来做回调函数

getStudent() {

    axios({

        method:"get", //请求方式
        url:"myServlet03.do?name=hhh"  //请求路径

            //使用箭头表达式=>代替原有的function来做回调函数
    }).then(result=> {

        this.id = result.data.id;
        this.name = result.data.name;
        this.age = result.data.age;
    })

}

第三种:传递参数可使用json格式,属性为params

getStudent() {

    axios({

        method:"get", //请求方式
        url:"myServlet03.do" , //请求路径
        params:{"name":"bbb"}  //传递参数

    }).then(result=> {

        this.id = result.data.id;
        this.name = result.data.name;
        this.age = result.data.age;
    })

}

get请求:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>mytitle</title>

    <script src="vue/vue-2.4.0.js"></script>
    <script src="vue/axios.min.js"></script>
  </head>
  <body>
    <div id="app">
      <button @click="getStudent">点击取得学生信息</button>
      <br><br>
      编号:<span>{{id}}</span><br>
      姓名:<span>{{name}}</span><br>
      年龄:<span>{{age}}</span><br>

    </div>
    <script>

      var vm = new Vue({
        el:"#app",
        data:{
          "id":"",
          "name":"",
          "age":""
        },
        methods:{
          /*getStudent() {
            /!*
              在请求执行成功后,执行回调函数中的内容,回调函数处于其他函数的内部,this不会与任何的
              对象绑定(以this.data的形式引入数据就引不到了)
              将指向vue对象的this赋值给外部方式定义的属性,然后在内部方法中使用该属性即可
            *!/

            var _this = this;

            axios({

              method:"get", //请求方式
              url:"myServlet03.do"  //请求路径
            }).then(function (result) {
              /!*
                注意:
                  之前使用vue-resource插件,对于值的处理,返回值.body的操作
                  这次使用axios插件,同样需要对值进行处理,返回值.data的形式
               *!/

              _this.id = result.data.id;
              _this.name = result.data.name;
              _this.age = result.data.age;
            })

          }*/

          /*getStudent() {

            axios({

              method:"get", //请求方式
              url:"myServlet03.do?name=hhh"  //请求路径

              //使用箭头表达式=>代替原有的function来做回调函数
            }).then(result=> {

              this.id = result.data.id;
              this.name = result.data.name;
              this.age = result.data.age;
            })

          }*/

          getStudent() {

            axios({

              method:"get", //请求方式
              url:"myServlet03.do" , //请求路径
              params:{"name":"bbb"}  //传递参数

            }).then(result=> {

              this.id = result.data.id;
              this.name = result.data.name;
              this.age = result.data.age;
            })

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

post请求:
上面的代码中只需将get改为post即可。

method: "post", //请求方式

第二种使用方式:

axios.get(

	""	//url
	{}	//param

)

get请求:

getStudent() {

    axios.get(
        "myServlet03.do",  //请求路径
        {
            params:{
                "name":"ww"
            }
        }
    ).then(result=>{
        var data = result.data;
        this.id = data.id;
        this.name = data.name;
        this.age = data.age;
    })
}

post请求:

getStudent() {

    axios.post(
        "myServlet04.do",  //请求路径
        {

            /*
              该方式发送数据是一个Request Payload的数据格式,一般的数据格式都是Form Data的格式
              所以我们之前写的以json形式的参数就发送不出去
              只能通过传统字符串的方法为后台发送参数
             */
            "name":"ww"
        }
    ).then(result=>{
        var data = result.data;
        this.id = data.id;
        this.name = data.name;
        this.age = data.age;
    })
}

总结:

​ axios的形式是一个基于Promise的HTTP请求客户端,用来发出请求。该形式也是Vue2.0官方推荐的形式,官方在推出了该形式后,同时就不再对之前的vue-resource的形式进行更新和维护了。所以更推荐的是使用axios的形式来处理ajax请求。

2.扩展:关于跨域请求的处理

同源:同源是指在一般情况下,浏览器发出请求访问的资源都是在相同的协议、域名和端口号下的,这样的请求即为默认同源策略的访问。

由于浏览器的同源策略,凡是发送请求URL的协议、域名、端口号三者之间任意一个(或者多个)与当前页面地址不同即为跨域。

在实际项目开发中,使用的当前页面有可能会发出这样的请求,访问的是非同源的资源,那么我们就需要进行跨域处理。

例如:

http:协议

192.168.1.1 ip地址:域名

8080:端口号

当前页面:

​ http://192.168.1.1:8080/xxx/xxx.jsp

发出请求:

​ http://192.168.1.1:8080/xxx/yyy.do

以上我们发出的请求的协议,ip,端口号完全相同,就是发出的是同源请求的操作。

发出请求:

​ https://192.168.1.1:8080/xxx/yyy.do 协议不同

​ http://192.168.1.2:8080/xxx/yyy.do 域名(ip)不同

​ 或者myweb.com访问baidu.com域名不同

​ http://192.168.1.1:8080/xxx/yyy.do端口号不同

以上请求协议,ip,端口号三大要素均有不同,需要进行跨域请求的操作。

跨域请求的常用处理方式:

(1)代理方式

​ 代理用于将请求发送给后台服务器,通过服务器来发送请求,然后将请求结果传递给前端。通过nginx代理来实现操作。

优点:跨域服务稳定

缺点:在使用到跨域处理的时候,必须要事先搭建nginx服务的代理环境,比较麻烦

(2)CORS方式

​ CORS是w3c标准的方式,通过在web服务器端的设置响应头Access-Control-Alow-Origin来指定哪些域可以访问本域的数据。

优点:使用简单,支持基于HTPP协议的所有请求方式

缺点:跨域服务响应稍慢

(3)jsonp方式

​ 通过动态插入一个script标签。浏览器对script的资源引用没有同源限制,同时资源加载到页面后会立即执行。

优点:使用简单,跨域服务响应快,获取的数据是我们最常用的json格式的数据

缺点:只能发送get请求,无法发送post请求

​ 由于在开发中发出跨域请求的目的通常是为了取得指定的资源数据,所以一般都是发出get请求,由于jsonp的形式使用简单,而且关于接收的响应数据,是程序员使用最多的json格式的数据,所以该形式在企业中应用的比较广泛。

对于资源的访问

对于分布式服务的访问

案例

需使用到两台服务器,所以需要用到eclipse的Tomcat和IDEA的Tomcat。

在eclipse中新建个Student类,和MyServlet01类。

MyServlet01.java:

@WebServlet("/getKyStudentData.do")
public class MyServlet01 extends HttpServlet {
	@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入到跨领域请求服务器,正在执行doGet方法...");
        
        //该服务器将要接收跨域请求
        //必须要接收一个跨域请求的参数叫做:callback
        
        String callback = req.getParameter("callback");
        
        Student s = new Student("ky-A0001","ky-zs","ky-23");
        
        JSONObject object = JSONObject.fromObject(s);
        resp.setContentType("application/json;charset=utf-8");
        
        resp.getWriter().println(callback+"("+object+")");
    }
}

在idea中新建个ky.jsp页面,

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>mytitle</title>

    <script src="vue/vue-2.4.0.js"></script>
    <%--
      想要处理跨域请求,我们就必须要使用vue-resource的方式
    --%>
    <script src="vue/vue-resource-1.3.4.js"></script>
  </head>
  <body>
    <div id="app">
      <button @click="getStudent">点击取得学生信息</button>
      <br><br>
      编号:<span>{{id}}</span><br>
      姓名:<span>{{name}}</span><br>
      年龄:<span>{{age}}</span><br>

    </div>
    <script>

      var vm = new Vue({
        el:"#app",
        data:{
          "id":"",
          "name":"",
          "age":""
        },
        methods:{
          getStudent() {

            /*
              案例:
                当前项目所在的服务器(idea的Tomcat)为:
                  协议:http
                  域名:localhost
                  端口号:8888

                将请求发送到以下配置的服务器(eclipse的Tomcat),来从跨域的服务器中接收数据
                  协议:http
                  域名:localhost
                  端口号:8081
             */

            //使用jsonp的方式发出跨域请求
            this.$http.jsonp("http://localhost:8081/vue/getKyStudentData.do").then(data=>{
              data = data.body;
              this.id = data.id;
              this.name = data.name;
              this.age = data.age;
            })
          }
        }
      })
    </script>
  </body>
</html>

执行结果:

在这里插入图片描述

Vuejs动画

在系统操作的过程中,用户体验有很多种,例如系统本身强大的功能体验,服务高效响应的体验,界面优化及视觉效果体验等等。其中视觉上的动画相关的体验,是带给用户最直观的体验。

系统页面中的动画,主要是用来以多元化的形式动态的展现信息。

在这里插入图片描述

需求:点击按钮,展现信息,再次点击按钮,隐藏信息

<body>
    <div id="app">

        <input type="button" value="点击" @click="flag=!flag"><br><br>

        <p v-if="flag">Hello Vue</p>

    </div>

    <script>

        var vm = new Vue({

            el: "#app",
            data: {

                "flag": false
            }
        })
    </script>
</body>

测试1:

我们第一次加入动画效果,对于Vuejs动画的引用,需要使用样式

.v-enter

.v-leave-to

.v-enter-active

.v-leave-active

测试2:

通过以上4组样式的设定,可以完成信息的动画展现

测试3:

我们先来完成简单的信息淡入淡出的效果以及滑入滑出的效果

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../lib/vue-2.4.0.js"></script>
    <!-- 自定义两组Vuejs的样式,来控制transition内部的元素实现动画的效果 -->
    <style>
        /*

            .v-enter 这是一个时间点,是进入之前元素的起始状态,此时还没有开始进入
            .v-leave-to  这是一个时间点,是动画离开之后,离开的终止状态,此时,元素动画已经结束了

        */

        .v-enter,
        .v-leave-to {
            /* 设置起始状态和结束状态元素的透明度为0(表示隐藏元素) */
            opacity: 0;

            /* 该形式为普通的淡入淡出的动画效果,使用起来最简单,应用的最广泛 */
            /* transform: opacity; */

            /* 滑入滑出 */
            transform: translateX(150px);
        }

        /* 
        
            .v-enter-active  这是一个时间段,表示元素入场的过程
            .v-leave-active  这是一个时间段,表示元素离场的过程

         */
        .v-enter-active,
        .v-leave-active {

            /* 设置在指定的时间内完成动画的全部入场和离场的过程 */
            transition: all 0.8s ease;
        }
    </style>
</head>

<body>
    <div id="app">

        <input type="button" value="点击" @click="flag=!flag"><br><br>

        <!-- 

            对于以下p标签中的信息,我们需要使用动画进行控制
            需要使用transition元素,将需要被动画控制的元素包裹起来,对于当前信息的展现,我们需要包裹的是p标签
            transition元素,Vue官方为我们提供的

         -->
        <transition>

            <p v-if="flag">Hello Vue</p>

        </transition>


    </div>

    <script>

        var vm = new Vue({

            el: "#app",
            data: {

                "flag": false
            }
        })
    </script>
</body>

</html>

测试4:

实现弹入弹出的效果

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../lib/vue-2.4.0.js"></script>
    <style>
        .v-enter-active {

            /* 设置弹进时长 */
            animation: bounce-in .5s;

        }

        .v-leave-active {

            /* 
                设置弹出时长 
                正常的弹入弹出,都需要将reverse属性值加上
            */
            animation: bounce-in .5s reverse;
        }

        /* 
        
            使用Vue搭配css动画效果的实现
            @keyframes:是CSS定义的动画规则
            bounce-in:表示弹入弹出的效果

         */

        @keyframes bounce-in {

            0% {
                transform: scale(0);
            }

            50% {
                transform: scale(1.5);
            }

            100% {
                transform: scale(1);
            }
        }
    </style>
</head>

<body>
    <div id="app">

        <input type="button" value="点击" @click="flag=!flag"><br><br>

        <transition>

            <p v-if="flag">
                Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!<br>
                Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!<br>
                Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!<br>
                Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!<br>
            </p>

        </transition>


    </div>

    <script>

        var vm = new Vue({

            el: "#app",
            data: {

                "flag": false
            }
        })
    </script>
</body>

</html>

测试5:

设置我们的v-前缀可以有效的区分不同元素使用动画

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../lib/vue-2.4.0.js"></script>
    <style>
        .tran1-enter-active {

            animation: bounce-in .5s;

        }

        .tran1-leave-active {

            animation: bounce-in .5s reverse;

        }

        .tran2-enter-active {

            animation: bounce-in 3.5s;

        }

        .tran2-leave-active {

            animation: bounce-in 3.5s reverse;

        }

        @keyframes bounce-in {

            0% {
                transform: scale(0);
            }

            50% {
                transform: scale(1.5);
            }

            100% {
                transform: scale(1);
            }
        }
    </style>
</head>

<body>
    <div id="app">

        <input type="button" value="点击1" @click="flag1=!flag1"><br><br>

        <transition name="tran1">
            <p v-if="flag1">
                Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!<br>
                Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!<br>
                Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!<br>
                Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!<br>
            </p>
        </transition>

        <br><br>

        <input type="button" value="点击2" @click="flag2=!flag2"><br><br>
        <transition name="tran2">
            <p v-if="flag2">
                Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!<br>
                Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!<br>
                Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!<br>
                Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!Hello Vue!<br>
            </p>
        </transition>


    </div>

    <script>

        var vm = new Vue({

            el: "#app",
            data: {

                "flag1": false,
                "flag2": false
            }
        })
    </script>
</body>

</html>

测试6:

使用第三方样式类库实现动画效果,这样就不用我们处理动画效果了,直接引用即可。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../lib/vue-2.4.0.js"></script>
    <link rel="stylesheet" href="../css/animate.css">
</head>

<body>
    <div id="app">

        <input type="button" value="点击" @click="flag=!flag"><br><br>

        <!-- 

            animate.css为我们提供了
            enter-active-class和leave-active-class
            用来操作元素进场和离场的效果

            以弹入弹出的形式处理进场和离场
            animated bounceIn
            animated bounceOut

         -->
        <!-- <transition enter-active-class="animated bounceIn" leave-active-class="animated bounceOut">
            <p v-if="flag">
                弹出的信息msg
            </p>
        </transition> -->

        <!-- 

            我们可以将class="animated"写在元素中
            这样在enter-active-class和leave-active-class中就不用重复写animated了

            使用  :duration="毫秒值"来统一设置入场和离场动画时长
         -->
        <!-- <transition enter-active-class="bounceIn" leave-active-class="bounceOut" :duration="400">
            <p v-if="flag" class="animated">
                弹出的信息msg
            </p>
        </transition> -->


        <!-- 

            使用  :duration="{enter:200,leave:400}"来分别设置入场和离场的时长

         -->
        <transition enter-active-class="bounceIn" leave-active-class="bounceOut" :duration="{enter:200,leave:600}">
            <p v-if="flag" class="animated">
                弹出的信息msg
            </p>
        </transition>

    </div>

    <script>

        var vm = new Vue({

            el: "#app",
            data: {

                "flag": false
            }
        })
    </script>
</body>

</html>

使用动画的钩子函数完成特殊的动画效果

测试7:

完成商品进入购物车的特效

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../lib/vue-2.4.0.js"></script>
    <link rel="stylesheet" href="../css/animate.css">

    <style>
        .ball {

            width: 15px;
            height: 15px;
            border-radius: 50%;
            background-color: #ff0000;
        }
    </style>
</head>

<body>
    <div id="app" style="height: 170px;">

        <input type="button" value="加入购物车" @click="flag=!flag">

        <!-- 

            以下@定义的属性,一会使用动画的钩子函数进行相应处理

         -->
        <transition @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">

            <div class="ball" v-show="flag"></div>
        </transition>

    </div>
    <img src="../image/gwc.png" alt="">

    <script>

        var vm = new Vue({

            el: "#app",
            data: {

                "flag": false
            },

            methods: {

                //注意:动画钩子函数也是具有参数的,一般都会有一个参数叫做el,这个el就是钩子函数的第一个参数
                //el表示的是要执行动画的那个DOM元素,是一个原生JS的DOM元素
                //大家也可以认为,el是通过document.getElementById("")的方式获取到的原生DOM对象

                beforeEnter(el) {

                    //beforeEnter表示动画入场之前,此时,动画尚未开始,可以在beforeEnter中,设置元素开始动画之前的起始样式
                    //el.style.transform设置小球开始动画之前的起始位置
                    //translate(0,0)表示的是在坐标0,0的位置
                    el.style.transform = "translate(0,0)"

                },

                enter(el, done) {

                    //这行代码,没有实际的作用,但是如果不写,就不会出现动画的效果
                    //可以认为,el.offsetWidth会强制启动动画
                    el.offsetWidth

                    //enter表示动画开始之后的样式的设置,这里,可以设置小球完成动画之后的结束状态
                    el.style.transform = "translate(150px,350px)";
                    el.style.transition = 'all 1s ease'

                    //这里的done,起始就是afterEnter这个函数,也就是说,done就是afterEnter函数的引用
                    done()
                },

                afterEnter(el) {

                    //在动画完成之后,会调用afterEnter
                    this.flag = !this.flag
                }
            }
        })
    </script>
</body>

</html>

测试8:

在信息列表中动态操作信息显示

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../lib/vue-2.4.0.js"></script>
    <link rel="stylesheet" href="../css/animate.css">
    <style>
        li {
            border: 1px dashed #999;
            margin: 5px;
            line-height: 50px;
            padding-left: 8px;
            font-size: 2px;
            width: 80%;
        }

        li:hover {
            background-color: hotpink;
            transition: all 0.8s ease;
        }

        .v-enter,
        .v-leave-to {
            opacity: 0;
            transform: translateY(60px);
        }

        .v-enter-active,
        .v-leave-active {
            transition: all 0.6s ease;
        }

        /* 
            下面的.v-move和 .v-leave-active需要配合使用,能够实现列表后续的元素,渐渐的飘上来的这种效果
        */
        .v-move {
            transition: all 0.6s ease;
        }

        .v-leave-active {
            position: absolute;
        }
    </style>

</head>

<body>
    <div id="app">

        <!-- 定义文本区域 -->
        <div>
            <label>
                Id:<input type="text" v-model="id">
            </label>

            <label>
                Name:<input type="text" v-model="name">
            </label>

            <input type="button" value="添加" @click="add">
        </div>

        <!-- 定义动画区域 -->
        <!-- 

            在我们实现列表过渡的时候,如果需要过渡的元素,是通过v-for循环渲染出来的,
                则不能使用transition进行包裹,必须使用transition-group来进行包裹
            如果要为v-for循环创建的元素设置动画,必须为每一个元素设置 :key属性(必须是当前的id)
            给transition添加appear属性,在页面中展现出来的时候,实现入场时候的效果
            通过为transition-group元素,设置tag属性,指定transition-group渲染为指定的元素
                如果不指定tag属性,默认渲染为span元素

         -->
        <transition-group appear tag="ul">

            <li v-for="(item,i) in list" :key="item.id" @click="del(i)">

                {{item.id}} --- {{item.name}}
            </li>

        </transition-group>

    </div>

    <script>

        var vm = new Vue({

            el: "#app",
            data: {

                id: "",
                name: "",
                list: [

                    { id: 1, name: '张三' },
                    { id: 2, name: '李四' },
                    { id: 3, name: '王五' },
                    { id: 4, name: '赵六' },
                    { id: 5, name: '孙七' }
                ]
            },

            methods: {

                add() {

                    //为列表添加对象
                    this.list.push({ id: this.id, name: this.name });
                    //将文本框中的数据清空掉
                    this.id = "";
                    this.name = "";
                },
                del(i) {

                    //根据下标删除所在行
                    this.list.splice(i, 1);
                }
            }
        })
    </script>
</body>

</html>

如果你觉得不错的话,就赶紧去B站学习吧,附上链接地址。个人觉得讲得超棒!
带你快速掌握vue、Vue.js-Vue.JS从入门到实战

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值