第二部分:Vue核心内容

2.1 Vue中的数据代理

2.1.1 数据代理原理

vue中的数据代理

  • 通过vm对象来代理data对象中属性的操作(读、写)

vue中数据代理的好处

  • 更加方便的操作data中的数据

基本原理

  • 通过Object.defineproperty()data对象中所有属性添加到vm

  • 为每一个添加到vm的属性,都指定一个gettersetter

  • gettersetter内部去操作(读、写)data中对应的属性

2.1.2 数据代理图示

 

2.1.3 Object.defineproperty()方法

参数 (obj, prop, descriptor)

  • obj 需要定义属性的对象

  • prop 需被定义或修改的属性名

  • descriptor 需被定义或修改的属性的描述符

方法描述

  • 该方法允许精确添加修改对象的属性

  • 一般情况下,我们为对象添加属性是通过赋值来创建并显示在属性枚举中(for…in 或 Object.keys 方法),但这种方式添加的属性值可以被改变,也可以被删除。

  • 而使用 Object.defineProperty() 则允许改变这些额外细节的默认设置。例如,默认情况下,使用 Object.defineProperty() 增加的属性值是不可改变的。

可选键值

  • configurable: 仅当该属性的 configurable 为 true 时,该属性才能够被改变,也能够被删除。默认为 false

  • enumerable: 仅当该属性的 enumerable 为 true 时,该属性才能够出现在对象的枚举属性中。默认为 false

  • value: 该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined

  • writable: 仅当仅当该属性的writable为 true 时,该属性才能被赋值运算符改变。默认为 false

  • get: 一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。该方法返回值被用作属性值。undefined

  • set: 一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认为undefined

获取、设置属性

var o = {}; // 创建一个新对象
​
// Example of an object property added with defineProperty with a data property descriptor
Object.defineProperty(o, "a", {
    value : 37,
    writable : true,
    enumerable : true,
    configurable : true
});
​
// 对象o拥有了属性a,值为37
var bValue;
Object.defineProperty(o, "b", {
    get : function(){ return bValue; },
    set : function(newValue){ bValue = newValue; },
    enumerable : true,
    configurable : true
});
​
​
o.b = 38;
// 对象o拥有了属性b,值为38
​
​
// 数据描述符和存取描述符不能混合使用
Object.defineProperty(o, "conflict", { 
    value: 0x9f91102, 
    get: function() { return 0xdeadbeef; }
});

2.2 Vue中的事件

2.2.1 事件的基本使用

  • 使用v-on:xxxx@xxxx 绑定事件,其中xxxx为事件名

  • 事件的回调需要配置在methods对象中,最终会在vm上

  • methods中配置的函数,不需要使用箭头函数!否则this就不是vm了

  • methods中配置的函数,都是被vue所管理的函数,this的指向是vm或组件对象

  • @click=”demo“ 与 @click=”demo($event)“ 的效果是一样的,但后者可以传参

2.2.2 事件修饰符

  • prevent:阻止默认事件(常用)

  • stop:阻止事件冒泡(常用)【如:点击按钮执行事件,冒泡到div上】

  • once:事件只触发一次(常用)

  • capture:使用事件的捕获模式

  • self: 只有 event.target 是当前操作元素时,触发处理函数

  • passive:事件默认行为立即执行,无需等待事件回调执行完毕

<!-- 点击shout只输出1,不会触发shout(2) -->
<div @click="shout(2)">
  <button @click.stop="shout(1)">ok</button>
</div>
 

2.3 Vue中的计算、侦听属性

2.3.1 使用插值计算

  • 插值语法:data中的值变换,插值重新计算

2.3.2 methods计算

  • 调用函数:data中的值变化,Vue中模板重新加载,函数肯定是要重新调用的

2.3.3 计算属性 computed

  • 定义

    • 要用的属性不存在,需要通过已有的属性计算得来

  • 原理

  • 底层借助于Object.defineProperty() 方法提供的getter、setter

  • get方法什么时候执行

    • 初次读取会执行一次,内部有缓存机制,依赖数据不变读取缓存

    • 所依赖的数据变化时,会被再次调用

  • 优势

    • 与methods相比,内部有缓存机制(复用),效率更高,调试更方便

  • 备注

    • 计算属性最终会出现在vm上,直接调用即可

    • 如果计算属性要被修改,那么必须写set函数去响应修改,且set中要引起计算时依赖的数据发生变化

computed:{
    // 函数中不能使用箭头函数
    fullName:{
        // 使用fullName时调用:由vm调用get
        get(){
            return this.firstName + "-" + lastName;
        },
        // 修改fullName时调用
        set(value){
            
        }
    }
}

2.3.4 侦听属性 watch

  • 被监视的属性变化时,回调函数自动调用,执行相关操作

  • 监视属性必须存在,才能进行监视操作

  • 监视属性的两种写法:

    • new Vue() 时候传入watch配置

    • 通过vm.$watch监视

// 写法1
watch:{
    info:{
        immediate:true,  // 初始化时候调用handler
        handler(newValue,oldValue){
            // 当info发生变化时执行
            console.log(oldValue,newValue)
        }
    }
 }
​
// 写法2
vm.$watch('info',{
     immediate:true,  // 初始化时候调用handler
     handler(newValue,oldValue){
        // 当info发生变化时执行
        console.log(oldValue,newValue)
     }
});

深度侦听

  • vue中的watch默认不监视对象内部的改变

  • 配置deep:true可以监视内部多层级属性的变化

  • vue自身可以对象内部变化,但是对于watch默认不提供监视内部变化,可以通过开始深度监视实现

// 监视多级结构中的属性变化
watch:{
    info:{
        deep:true,  // 开启深度监视
        handler(){
            // 当info、内部值变化时执行
            console.log("info发生了变化...")
        }
    }
 }

2.3.5 计算、侦听属性的区别

  • computed能完成的功能,watch都能完成

  • watch能完成的功能,computed不一定能完成,比如:watch可以进行异步操作

  • 两个重要原则:

    • 所有被vue管理的函数,最好写成普通函数,这样this的指向才是vm,或者指向组件实例对象

    • 所有不被vue管理的函数(定时器函数,ajax回调函数),最好写成箭头函数,这样this才能指向vm、组件实例

    • 可参照 【Vue中this指向问题】

2.4 Vue中的样式

2.4.1 class样式

  • 写法: :class ="xxx" ,xxx可以是字符串、数组、对象

  • 字符串写法适用于:类名不确定,要动态获取

  • 对象写法适用于:要绑定多个样式,个数不确定,名字也不确定

  • 数组写法适用于:要绑定多个样式,个数、名字确定,就是不知道用不用

2.4.2 style样式

  • :style=“{fontSize:xxx}”,其中xxx是动态值

  • :style="[a,b]",其中a,b不带双引号是样式对象,带双引号是样式名称

2.5 条件渲染

2.5.1 v-if

  • 写法:

    • v-if =“条件”

    • v-else-if=“条件”

    • v-else

  • 适用于:切换频率比较低的场景

  • 特点:不展示的dom元素直接被移除

  • 注意:中间必须相连,结构不能被打断

  • 组合使用<template>可将条件包裹,不改变原有结构

2.5.2 v-show

  • 写法:v-show=“表达式”

  • 适用于:切换频率比较高的场景

  • 特点:不展示的dom未被移除,只是使用样式隐藏

2.5.3 备注

  • 使用v-if时,元素可能无法获取,使用v-show一定可以获取到【v-if元素会移除】

2.6 v-for循环key的原理

2.6.1 虚拟DOM中key的作用

  • key是虚拟DOM对象的标识

  • 当数据发生变化时,Vue会根据 新数据 生成 新的虚拟DOM

  • 随后Vue会进行 新虚拟DOM旧的虚拟DOM 的差异比较

2.6.2 虚拟DOM对比规则

  • 旧虚拟DOM 中找到了与 新虚拟DOM 中相同的key

    • 若虚拟DOM内容没有变,直接使用之前的真是DOM

    • 若虚拟DOM中内容变了,则生成新的真是DOM,随后替换页面中之前的真是DOM

  • 旧虚拟DOM 中未找到与 新虚拟DOM 相同的key

    • 创建新的真是DOM,随后渲染到页面中

2.6.3 index作为key可能会引发的问题

  • 若对数组进行逆序添加、逆序删除等破坏顺序的操作:

    • 会产生没有必要的真是DOM更新

    • 界面显示没有问题,但是效率低下

  • 若数组结构中还包含输入类的DOM:

    • 会产生错误的DOM更新

    • 界面显示顺序有问题

2.6.4 index作为key执行原理

  • 默认值作为key,会默认使用index作为key

 

2.6.5 元素id作为key执行原理

  • 使用元素中唯一标识作为key【推荐做法】

  • 数组随意插入,效率高、数据不会错乱

 

2.7 Vue监测数据改变的原理

2.7.1 数据监测流程

1.加工data

  • data与_data中的数据是不一样的,vue对数据进行加工

  • _data中做了数据劫持,增加getter、setter

2.赋值vm._data

  • 将data值赋值给vm._data

3.简单的处理流程

 

2.7.2 数据监视原理

如何检测对象中的数据

  • 通过setter实现监视,且要在new vue() 时候就要传入要监视的数据

  • 对象中后追加的数据,vue不做响应式处理

  • 如需给后追加的数据做响应式处理,可以使用API:

    • Vue.set(target, propertyName/index, value)

    • vm.$set(target, propertyName/index, value)

如何监视数组中的数据

  • 通过包装数组中更新数据的方法实现,本质上就做了两件事情:

    • 调用数组原生更新方法,对数组进行更新

    • 重新解析模板,进而更新页面

  • 在vue中修改数组中某个元素,一定要使用如下方法:

    • 使用包装API:push、pop、shift、unshift、splice、sort、reverse

    • 使用Vue.set() 或者 vm.$set()

特别注意

  • Vue会监视data中所有层次的数据

  • Vue.Set()vm.$set() 不能给 vm 或者 vm 根对象添加数据。

2.8 Vue中的过滤器

2.8.1 定义

  • 对于显示的数据进行特定格式化后再显示

  • 适用于简单的逻辑处理,负责逻辑使用函数处理

2.8.2 语法

  • 注册过滤器:Vue.filter(name, callback) 或 new Vue(filters: {})

  • 使用过滤器:{{ xxx | 过滤器名 }} 或 v-bind:属性 = " xxx | 过滤器名"

2.8.3 备注

  • 过滤器也可以接收额外参数、多个过滤器也可以串联使用

  • 并没有改变原来的数据,只是产生新的对应的数据

<h3>现在的时间:{{time | timeFormatFilter}}</h3>
​

2.9 Vue中的内置指令

2.9.1 v-text 指令

  • 作用:向所在节点中渲染文本内容

  • 与插值语法的区别:v-text会替换节点中所有内容,插值语法不会

2.9.2 v-html 指令

  • 作用:向指定节点中渲染包含html结构的内容

  • 与插值语法的区别:

    • v-html会替换节点中的所有内容,插值语法不会

    • v-html会识别html结构

  • 严重注意:

    • 在网站上动态渲染任意的html是非常危险的,会导致XSS攻击

    • 一定要在可信的内容上使用v-html,永远不要在用户提交内容上使用

2.9.3 v-cloak 指令

  • 没有值的

  • 本质上是一种特殊属性,vue实例创建完毕接管容器后,会删除v-cloak属性

  • 使用v-cloak配合css可以解决:网速慢时,页面加载出现 {{xxxxx}} 问题

2.9.4 v-once 指令

  • v-once所在的节点在初次动态渲染后,就视为静态内容了

  • 以后数据变化,不会影响v-once所在结构的更新,可以用于优化性能

2.9.5 v-pre 指令

  • 可以让vue跳过所在节点的编译过程

  • 可利用其跳过:没有使用指令语法、没有插值语法的节点,会加快编译

2.10 自定义指令

2.10.1 定义

  • 使用js底层操作DOM,实现指令操作

  • 在Vue中 direxctives:{} 里面是定义的指令

2.10.2 自定义方式

  • 函数模式:

    • 使用函数模式 big(element, binding)

    • element为当前使用指令的节点元素,binding为指令绑定的值

  • 钩子函数模式:

    • 内置三个生命周期函数:不能改变名称,只能在函数中实现功能

    • bind(element, binding):指令与元素成功绑定就执行

    • inserted(element, binding):指令所在元素被插入页面时执行

    • update(element, binding):指令所在的模板被重新解析时执行

 

2.10.3 自定义语法

  • 局部指令:

    • new Vue({ directives: { 指令名:配置对象 } })

    • new Vue({ directives{ 指令名:配置对象 } })

  • 全局指令:

    • Vue.directives( 指令名,配置对象 )

    • Vue.directives( 指令名,回调函数)

  • 注意:

    • 指令定义时不加 v- ,但是使用时需要加 v-

    • 指令名如果是多个单词,使用kebab-case命名方式,不要使用 camelcase 命名

2.11 Vue生命周期

2.11.1 生命周期的定义

  • 别名:生命周期函数、生命周期回调函数、生命周期钩子

  • 是什么:Vue在关键时候帮我们调用的一些特殊名称的函数

  • 生命周期函数名称不能更改,但是函数内部可以由程序员根据需求进行编写

  • 生命周期函数中 this 指向VM 或者 组件实例对象

2.11.2 VM的生命周期

  • 将要创建 ===> 调用beforeCreate函数

  • 创建完毕 ===> 调用created函数

  • 将要挂载 ===> 调用beforeMount函数

  • 挂载完毕 ===> 调用mounted函数 【重要的钩子函数】

  • 将要更新 ===> 调用beforeUpdate函数

  • 更新完毕 ===> 调用updated函数

  • 将要销毁 ===> 调用beforeDestroy函数 【重要的钩子函数】

  • 销毁完毕 ===> 调用destroyed函数

2.11.3 生命周期函数使用注意事项

  • 常用的生命周期钩子函数:

    • mounted:发送ajax请求、启动定时器、绑定自定义事件、订阅消息等

    • beforeDestroy:清除定时器、解绑事件、取消订阅消息等

  • 关于销毁Vue实例:

    • 销毁后借助Vue实例看不到任何信息

    • 销毁后自定义事件会失效,但是原生DOM事件依然有效

    • 一般不会在beforeDestroy中操作数据,因为即便是操作数据,也不会再触发更新流程了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值