1、Vue

Vue

Vue的特点

  1. 非常简单,Easy,好学
  2. 遵循一种新的WEB架构模式: MVVM
  3. 它可以开发单页面的应用程序(每个单独的页面,就是一个独立的应用程序)
  4. 渐进式(从核心技术开发,一层一层的添加内容)与兼容性(允许兼容其他框架或其他技术)
  5. 视图组件化
  6. 虚拟 DOM(Virtual DOM)

MVVM架构

说明: clipboard.png

视图组件化

将网页拆分成多个组件,然后各自开发

说明: clipboard.png

最后,再拼接各个组件,通过拼接组件的方式,完成页面的开发 (类似于:Spring拼接组件)

虚拟DOM(Virtual DOM)

以前,很不规范的人在使用Jquery时,存在大量的针对DOM节点进行频繁的操作,这就导致浏览器在解析节点时,显得非常的卡顿

为了解决这个问题,所以前端提出了 Virtual DOM的说法,Virtual DOM实际上是在内存中,先定义一颗节点树,所有的操作先针对该节点树进行完成,操作完毕之后,再同步到真实DOM对象中,从而提升浏览器在解析节点时的性能浪费

Vue的使用

1、引入vue

引入js文件

官网下载:https://cn.vuejs.org/

1)引入本地的vue.js文件

2)引入网络,CDN加速vue.js

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>

2、声明Vue实例

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <div id="app">
            <!--   声明式渲染   -->
            {{t1}}
        </div>
    </body>
    <script>
        //创建vue对象,参数是一个配置对象
        var v = new Vue({
            //用于指定Vue实例服务哪个容器
            el:"#app",
            //声明的属性值
            data:{
                t1:"test1",
            },
            //声明的方法
            methods:{
                add(){
                    alert("add....")
                },
            }
        });
        //Vue实例的el,也可以是用对象v的原型对象方法$mount(),进行挂载
        //v.$mount("#app")
    </script>
</html>

注意:一个Vue实例只可以对应一个容器,也就是如果el赋值了一个类选择器,也只会有一个生效;同样多个Vue实例也不可以对应同一个实例。

数据代理:通过对象v可以调用属性t1,实际上,对象v的属性是由Object.defineProperty()方法完成的对_data属性(Vue将data存入了自身的_data属性)的代理,例如:

let myVue = {
    data:{
        name: "lucy",
        address: "zh"
    }
}
Object.defineProperty(myVue,"name",{
    get(){
        return myVue.data.name
    },
    set(value){
        myVue.data.name = value
    }
})

myVue.name = "tom" //此时修改的myVue的name属性就是调用set()方法修改的
console.log(myVue.name) //此时读取的myVue的name属性就是调用get()方法读取的
// tom

模板语法

字符串拼接

<a :href="'detailPage.html?workorderId=' + li.workorderId">详情</a>

声明式渲染(mustache语法)

mustache语法中,不仅仅可以写变量,也可以写简单的表达式

格式:{{ message }}

标签使用v-pre属性的话,那么mustache语法不会被解析

标签可以使用v-cloak属性的话,只有在vue解析该标签的话,这个标签才会进行展示并且删除该属性(需要和css进行搭配,[v-cloak]{display:none})

v-once

如果标签添加这个属性,那么该标签只会展示首次的数据,不会随变量改变而发生界面改变

v-html&v-text

v-html可以给当前标签添加文本,并解析html标签元素

v-text可以给当前标签添加文本,但是不解析标签元素

v-on

v-on可以给节点添加事件

<!--方法没有形参的情况下()可以省略-->
<button v-on:click="add">botton</button>
<button v-on:click="add(1)">botton</button>
<!-- 简写 -->
<button @click="add">botton</button>
<button @click="add(1)">botton</button>

支持的事件

  1. click在元素上按下并释放任意鼠标按键。
  2. dblclick在元素上双击鼠标按钮。
  3. mousedown在元素上按下任意鼠标按钮。
  4. mouseenter指针移到有事件监听的元素内。
  5. mouseleave指针移出元素范围外(不冒泡)。
  6. mousemove指针在元素内移动时持续触发。
  7. mouseover指针移到有事件监听的元素或者它的子元素内。
  8. mouseout指针移出元素,或者移到它的子元素上。
  9. mouseup在元素上释放任意鼠标按键。
  10. pointerlockchange鼠标被锁定或者解除锁定发生时。
  11. pointerlockerror可能因为一些技术的原因鼠标锁定被禁止时。
  12. select有文本被选中。
  13. wheel 滚动鼠标滚轮时

传参

<div id="app">
    <!-- 如果调用方法没有()的话,那么默认方法形参为当次触发事件的event对象 -->
    <button @click="cli">click</button>
    <!-- 如果需要event对象,也需要其他参数(多参数),那么使用$event -->
    <button @click="cli($event,lucy)">click</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
    let v = new Vue({
        el:"#app",
        methods: {
            //方法定义了形参
            cli:function(event){
                console.log(event);
            }
        }
    })
</script>

修饰符

@click.stop="",阻止当前事件的冒泡

@click.prevent="",阻止默认事件,例如点击提交按钮后form表单的默认提交事件

@keyup.keyCode|keyAlias="",监听键盘的点击

@click.once="",当前事件只会触发一次

@click.self="",只有当前事件target是当前元素时才会触发

@click.capture="",当前元素在捕获阶段处理事件

@click.native="",用于给组件绑定原生的事件

v-bind

v-bind命令的作用: 可以用来定义标签的属性,单向绑定,也就是变量如果发生变化,那么页面随之发生变化,但是如果页面变化,变量不会变化

<input type="text" v-bind:value="t1"/>
<!-- 简写 -->
<input type="text" :value="t1"/>

绑定class

<style>
    .redColor{
        color:red;
    }
</style>
<div id="app">
    <!-- 此处:class可以通过一个对象,来绑定多个class,{类名1:boolean,类名2:boolean} -->
    <h1 :class="{redColor:isRed}">hello world!</h1>
    <button @click="isRed = !isRed">切换颜色</button>
</div>
<script>
    let v = new Vue({
        el:"#app",
        data:{
            isRed:true
        }
    })
</script>

:class也可以通过一个数组来动态绑定,:class="['类名1','类名2']"

v-model

v-model 主要可以做到:view 与model 之间,双向绑定,只可以作用在表单元素上,也就是model的数据变化,view那边可以跟着变化; view的数据变化,model的数据跟着也会发生变化,实际是v-bind和v-value的结合

<input type="text" v-model="t1"/>

v-if

v-if是条件渲染指令,它根据表达式的真假来删除和插入元素

<!--此元素会从dom中删除-->
<input type="text" v-if="1 < 0"/>

v-else&v-else-if

v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。

<div v-if="type === 'A'">
  A
</div>
<div v-else-if="type === 'B'">
  B
</div>
<div v-else>
  Not A/B/C
</div>

v-show

v-show可以做到DOM节点,进行条件显示,频繁切换建议使用v-show

和v-if的区别

<!--会给此元素加style="display:none"-->
<input type="text" v-show="1 < 0"/>

v-for

遍历循环添加元素

遍历数组

<!--goods:[{name:"apple",price:18},{name:"banana",price:22}]-->
<!--g为遍历出来的每个对象,index为索引-->
<tr v-for="(g,index) in goods">
    <td>{{g.name}}</td>
    <td>{{g.price}}</td>
</tr>

遍历对象

<!--t1:{name:"apple",price:18}-->
<!--value为对象的属性值,key为对象属性名-->
<div v-for="(value,key) in t1">
    {{value}}==={{key}}
</div>

自定义指令

是用Vue配置项directives进行声明

<body>
    <div id="app">
        <div v-log="123"></div>
    </div>
</body>
<script>
    Vue.config.productionTip = false;
    new Vue({
        el:"#app",
        directives: {
            log(element,binding){
                console.log("自定义指令");
                console.log(element);
                console.log(binding);
            }
        }
    });
    //自定义指令
    //div dom对象
    //{name: 'log', rawName: 'v-log', value: 123, expression: '123', modifiers: {…}, …}
</script>

定义全局指令

Vue.directive("log",function(element,binding){
    console.log("自定义指令");
    console.log(element);
    console.log(binding);
})

Vue的生命周期

生命周期:就是指Vue对象从产生到服务到死亡(GC回收)的完整过程。

在Vue的整个生命周期过程中,跟Servlet一样会执行很多的默认方法(init(),service(),destroy()) ,同样也定义了非常多的默认方法,在前端,他们把这些默认方法,称为:钩子函数

Vue获取DOM元素

除了vue的方法以外,还可以使用jquery或js的方法来获取

<div id="app">
    <input ref="name">
    <button @click="m1">get</button>
</div>
<script>
	let vm = new Vue({
       el:"#app",
       methods:{
           m1(){
               //使用this.$refs.DOM元素ref属性值,获取该DOM元素
               console.log(this.$refs.name.value);
           }
       }
    });
</script>

监听属性

使用watch属性,进行监听属性

在vue形参外监听

var vm = new Vue({
    el: '#app',
    data: {
        counter: 1
    }
});
//监听counter这个属性改变前后的值
vm.$watch('counter', function(after, before) {
    alert('改变前为:' + before + ' ,改变后为: ' + after);
});
//一个形参代表改变后的值
vm.$watch('counter', function(after) {
    alert('改变后为:' + after);
});

在vue形参内监听

var vue = new Vue({
    el:"div",
    data:{
        test:"111",
    },
    watch:{
        test:function (after, before){
            alert('改变前为:' + before + ' ,改变后为: ' + after);
        }
    }
});

immediate

立即监听,也就是组件创建完成后就进行一次监听

var vue = new Vue({
    el:"div",
    data:{
        test:"111",
    },
    watch:{
        //此时监听属性的值应该是一个对象,才可以添加配置项
        test:{
            immediate: true,
            handler(after, before){
                alert('改变前为:' + before + ' ,改变后为: ' + after);
            }
        }
    }
});

deep

深度监视,也就是可以监听多层结构的数据

var vue = new Vue({
    el:"div",
    data:{
        test:{
            a: 1,
            b: 2
        },
    },
    watch:{
        //此时监听属性的值应该是一个对象,才可以添加配置项
        test:{
            deep: true,
            handler(after, before){
                alert('改变前为:' + before + ' ,改变后为: ' + after);
            }
        }
    }
});

计算属性

虽然在模板中可以直接插入data中的数据,但是有些时候,我们需要对数据进行一些转化,然后才可以使用,或者需要将data中的多个数据结合起来使用,所以需要使用computed实例

基本使用

<div id="app">
    <!-- 使用不需要加小括号,因为是一个属性 -->
    <h1>{{fullName}}</h1>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
    let v = new Vue({
        el:"#app",
        data:{
            firstName:"Kobe",
            lastName:"Bryant"
        },
        computed:{
            //计算属性,结果可以看做为一个属性
            fullName:function(){
                return this.firstName + " " + this.lastName;
            }
        }
    })
</script>

本质

计算属性的本质是一个数据代理对象,有getter和setter两个方法,我们直接使用属性名,实际是调用了get方法,我们一般也只会实现getter方法,这个属性也成为只读属性

computed:{
    fullName{
        get:function(){

        },
        set:function(newValue){

        }
    }
}

computed和methods的区别

1、使用methods的话,在每次调用,都会执行一次方法

2、使用computed的话,在首次调用,会执行一次,但是后续调用该属性,如果函数里面的数据没有发生改变的话,那么vue会使用自带的缓存

过滤器

用来对数据进行过滤,例如,价格保留两位小数,并加单位(元):

<div id="app">
    <!-- 显示格式为:"data | 过滤器" -->
    {{price | showPrice}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
    let v = new Vue({
        el:"#app",
        data: {
            price:98
        },
        filters: {
            showPrice(price){
                return price.toFixed(2) + "元";
            }
        }
    })
</script>

全局过滤器

Vue.filter("showPrice",function(value){
    return price.toFixed(2) + "元";
})

计算属性、过滤器的区别

计算属性

1、计算属性适合用在单个属性的计算; 2、计算属性只能在单个vue实例中使用; 3、计算属性不能接收参数,只能使用data中定义的变量进行计算; 4、计算属性有缓存机制,可减少调用次数; 5、计算属性相当于定义一个变量

过滤器

1、过滤器适合多个同样计算方法的属性的计算; 2、过滤器可以定义为全局过滤器,在多个vue实例中使用; 3、过滤器可以接收多个参数进行计算; 4、过滤器没有缓存机制,每调用一次都会计算一次; 5、过滤器相当于定义一个特殊的方法

$nextTick

语法:$nextTick(function(){})

作用:在下一次DOM更新结束再执行其回调函数

用处:由于Vue并不是在数据更改后就立刻更新DOM,而是在当前的函数执行完后才更新,所以如果当前操作需要依托更新后的DOM,那么就需要使用这个方法