Vue概念(部分)

设计模式

观察者模式、发布订阅模式

区别

发布订阅:Event就是调度中心 只有一个类 提供发布和订阅功能解耦
观察者模式:有两个类,观察目标observer观察者subject耦合,一旦观察目标变化需要观察者做出反应
所以单纯从结构来看可以看出两个设计模式的区别

发布订阅模式

可以认为是观察者模式的升级版

优点

灵活,由于订阅发布模式的发布者和订阅者是解耦的,只要引入订阅发布模式的事件中心,无论在何处都能发布订阅。同时订阅发布者之间不影响。(发布订阅,订阅者不把自身this放入调度中心,而是注册回调就行,同时这也是为什么父子通信是单向的原因)

缺点

容易导致代码不好维护,有一些灵活,同时也是缺点,使用不当会造成数据流混乱,导致代码不好维护

观察者模式

优点

响应式目标变化就会通知观察者,这是观察者最大的优点,也是因为这个优点,观察者在前端才会这么出名

缺点

不灵活,相比订阅发布模式,由于目标和观察者是耦合在一起的,所以观察者模式需要同时引入目标和观察者才能达到响应式的效果。而订阅发布模式只需要引入事件中心,订阅者和发布者可以不在一处

模板编译

概述:Vue的编程过程就是将template转化为render函数的过程,会经历三个阶段
生成AST树、优化、codegen(将优化后的AST树转换为可执行的代码)

生命周期

1、beforeCreate在实例初始化后,数据观测(data observer)和event/watcher事件配置前被调用
2、created 实例已经创建完成之后被调用。在这一步实例已经完成以下的配置:数据观测(data observer),属性和方法的运算,watch/event事件回调。这里没有$el
3、beforeMount 在挂载开始之前被调用:相关的render函数首次被调用
4、mounted el被新创建的vm. $el替换,并挂载到实例上去之后调用该钩子
5、beforeUpdate数据更新时调用,发生在虚拟DOM重新渲染和打补丁之前
6、updated发生在更新完成后当前阶段组件Dom已经完成更新。要注意的是避免在此期间更改数据,因为这可能会导致无限循环的更新
7、beforeDestroy实例销毁之前调用。在这一步实例仍然可以使用
8、destroy Vue实例销毁后调用。调用后,Vue实例指示的所有东西都会解绑,所有的事件监听器会被移除,所有的子实例也会被销毁,该钩子在服务器端渲染期间不会被调用

全局API

MIXIN

主要调用mergeOptions方法合并options配置

extend

基于原型式继承也就是Object.create继承Vue构造函数,并调用mergeOptions合并配置,返回一个新的Vue子类

set

同vm. $set

nextTick

同vm. $nextTick

实例属性和方法

$nextTick

1、nextTick批量异步更新策略,一句话概括在下次DOM更新循环结束之后执行延迟回调。它主要是是为了解决:例如一个data中的数据它的改变会导致视图的更新,而在某一个很短的时间被改变了很多次,假如是1000次,每一次的改变如果都将促发数据中的setter并按流程跑下来直到修改真实DOM,那DOM就会被更新1000次,这样的作法肯定是非常低效的。
2、 而且目前浏览器平台并没有实现nextTick方法,所以Vue.js源码中分别用Promise,Observer,setTimeout,setlmmediate等方式定义了一个异步方法nextTick,它接收的是一个回调函数,多次调用nextTick会将传入的回调函数存入队列中,当当前栈的任务都执行完毕后才来执行这个队列中刚刚存储的那些回调函数并通过这个异步方法清空当前队列。

MutationObserver

监听dom变化,是个微任务

let observe = new MutationObserver(
flushCallbacks)
observer.observe

采用文本节点内容变化 触发flushCallbacks回调

computed计算属性

1、计算属性即是依赖也是观察目标,同时具有缓存特点,所以实现这三个特点也就实现了计算属性。计算属性作为依赖,初始的时候会创建计算属性watcher,观察者存在values属性和get方法。computed属性的getter函数会在get方法中调用,并将返回值赋值给valu,一但计算属性所依赖的数据更新,就会通知计算属性watcher,就会执行get方法,我们就可以拿到value
2、在初始化计算属性watch的时候,我们会传入lazy属性表明它是一个计算属性watcher,而其内部也会初始化一个dirty属性,计算属性所依赖的数据更新,这时候dirty会置为true,会重新执行getter方法重新拿到值,如果数据依赖没有发生变化,此时dirty就会false,会拿到缓存的值,这样就实现了计算属性
3、当computed作为观察目标时,因为我们会在模板中使用到它,所以要为他收集依赖,但是实际computed实际是依赖于data属性变化而变化,为computed收集依赖实际就是帮computed所依赖的data属性收集依赖,所以watcher内部维护了一个dep,存储了watcher被那些dep所存储,vue内部还维护了一个watcher栈,此时通过这个栈我们就可以为观察目标dep推入一个渲染watcher达到了为计算属性收集依赖的目的

$watch

1、watch用于监控用户的data变化,数据变化后会触发对应的watch的回调方法。watch属性实现是合并配置,将对象形式,数组形式,字符串形式统统转化为key-value形式内部调用$watch方法,这个方法会创建一个用户watcher传入user为true的配置watcher存在get方法。而watch属性传入的getter方法是key值,会内部将这个key值转化为函数,目的是触发依赖收集当这个data变化时,再触发callback
2、Vue中computed和watch的区别?
computed和watch都是基于Watcher来实现的,computed是具有缓存特性的(默认不执行)只有当取值时执行,内部依靠dirty变量实现缓存效果。watch则是默认会执行一次属性之变化后触发回调函数

$set

1、如果修改的是数组对象,则通过splice来进行修改
2、如果是对象通过defineReactive内置方法将该新增的属性变为响应数据,每个引用类型属性都绑定了一个__ob__这个ob指向vm,通过vm.dep.notify触发依赖更新

$forceUpdate

每个组件就是一个vue实例,实例下都有一个对应的渲染watcher属性_watcher,触发vm._watcher.update就会更新页面

$on、 $emit…

自定义事件基于发布订阅实现,然后是存在实例的_events对象上的(vm就是一个调度中心)

指令

概述

vue中的指令,vue中都是以v-开头(一般用来操作dom)

v-for

1、v-for和v-if连用问题
v-for会比v-if的优先级高一些,如果连用的话会把v-if给每个元素都添加一下,会造成性能的问题(使用计算属性优化)
2、从AST转化成JS语法的时候内部会调用一个_l的函数,参数为n表示循环几次

v-if

1、v-if如果条件不成立不会渲染当前指令所在节点的dom元素
2、从AST转化为JS语法的时候v-if会被转化为三元表达式

v-show

v-show只通过样式切换当前dom的显示或者隐藏

v-model

v-model的本值是一个语法糖,可以看成是value+input方法的语法糖。可以通过model属性的prop和event属性来进行自定义。原生的v-model,会根据标签的不同生成的事件和属性

应用在组件上

就是一个语法糖,解析成value和事件挂载到propsData,被当成组件的props属性(一个组件上的v-model默认会利用名为value的prop和名为input的事件)

应用在标签上

真正的一个指令

v-on

绑定事件监听器,事件类型由参数指定。表达式可以是一个方法的名字或一个内联语句,如果没有修饰符也可以省略。缩写“@”
注意不要和$on混淆

vm.$on:监听当前实例上的自定义事件。

事件可以由"vm.$emit"触发。回调函数会接收所有传入事件触发函数的额外函数

v-bind

v-bind:动态地绑定一个或者多个attribute,或者一个组件prop到达表达式。缩写:“:”
主要是通过ast语法解析,实现的将对应属性转化成变量

自定义指令

概述:我们可以自定义vue中的指令来实现功能的封装(全局指令、局部指令)

指令定义对象可以提供如下几个钩子函数

1、bind:只调用一次,指令第一次绑定到元素时调用
2、inserted:被绑定元素插入父节点时调用
3、update:所在组件的VNode更新时调用,组件更新前状态
4、componentUpdated:所在组件的VNode更新时调用,组件更新后的状态
5、unbind:只调用一次,指令与元素解绑时调用

Vue插件开发

通过Vue.use来注册插件(如果插件是一个对象,必须提供install方法。如果插件是一个函数,它会被作为install方法,install方法调用时,会将Vue作为参数传入)

vue-lazyload

懒加载原理

一开始不给src添加值这样渲染的时候不加载图片。
判断图片是否在可视区域,跟据滚动事件判断记得节流
是的话通过new Image()请求图片 核心再设置setAttribute

判断是否在可视区域
let{top}=this.el.getBoundingClientRect();
return top<window.innerHeigth
加载图片
const loadimageAsync=(src,resolve,reject)=>{
let image=new Image();
image.src=src;
image.onload=resolve;
image.onerror=reject
}
vue-lazyload插件原理

声明一个ReactiveListener类,一个图片相当于ReactiveListener一个实例。
只要通过v-lazy指令就会创建一个实例然后push到istenerQueue队列,实例具有checkinView判断该实例是否在可视区域,load请求加载图片。
监听最外层父级dom滚动事件,触发scroll事件时,其回调函数就会调用checkinView,如果为true则调用load进行加载图片

虚拟DOM与DIFF算法

什么是虚拟DOM

虚拟DOM本质上是javaScript对象,是对真实DOM的抽象

Vue为什么需要虚拟DOM

要进行diff检测差异,操作真实DOM浪费性能。速度快,减小了页面渲染过程的次数

DIFF算法

vue中的diff算法由patch方法实现 传入旧节点和新节点进行同层级比对

对比标签

如果标签类型不一样:直接替换
判断是否是文本节点,是的直接更新文本节点

如果标签类型一样
1、 对比属性
2、对比子元素:

2-1、 旧节点没有子元素,新节点有子元素
2-2、 旧节点没有子元素,新节点没有子元素
2-3、 旧节点和新节点都有子元素(核心 采用双端比较):

2-3-1、 vue中调用updateChildren这个核心方法,它是这样操作的:
声明四个指针,老节点的首尾指针,新节点的首尾指针,然后进行新旧节点的双端比较,然后我们接着进入diff过程,每一轮都是同样的对比,其中某一项命中了,就递归的进入patchVnode又有children,那么还会来到这个diff children的过程
2-3-2、 旧首节点和新首节点用sameNode对比
2-3-3、 旧尾节点和新尾节点用sameNode对比
2-3-4、 旧首节点和新尾节点用sameNode对比
2-3-5、 旧尾节点和新首节点用sameNode对比
2-3-6、 暴力对比:如果以上逻辑都匹配不到,再把所有旧子节点的key做一个映射到旧节点下标的key->index表,然后用新vnode的key去找出在旧节点中可以重复用的位置。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值