从面试官的角度带你从源码分析关于vue(v2.7.10)的面试题

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

我们在面试的时候经常会被问到vue框架的原理类问题我今天整理了一些常见问题和答案希望有不正确之处还请指正。

1.new Vue时发生了什么

首先实例化一个对象该对象执行init方法初始化生命周期等等随后执行$mount方法开始生成vnode和dom。其中el会作为根dom然后会根据render生成vnode。
在这里插入图片描述
执行init方法
在这里插入图片描述
开始挂载
在这里插入图片描述
判断有无render函数没有则会生成
在这里插入图片描述

h函数就是$createElement调用该方法生成vnode
在这里插入图片描述
总结new Vue时会触发vue的_init方法去初始化数据将el作为根dom然后调用$mount方法去挂载组件挂载的过程中会执行_render方法生成vnode。

2.双向数据绑定的原理

所谓的双向数据绑定就是当数据改变时视图也跟着变化接下来我们看看关键代码。首先在get方法中会判断Dep.target是否存在target是watcher实例在视图中或者函数中获取该变量就会触发变量的get方法。然后该变量的dep实例就会放入当前的watcher建立变量和watcher的联系。
在这里插入图片描述
在这里插入图片描述
在set的时候即数据发生修改的时候会执行当前变量的dep实例的notify方法该方法会遍历执行当前观察的视图所有的watcher的update方法去异步更新视图。
在这里插入图片描述
在这里插入图片描述
总结双向绑定的原理就是利用Object.defineProperty去设置变量的get和set方法在该函数中会实例化dep数组。在获取数据的时候会触发变量的get方法去收集watcher当变量发生改变时会触发变量的set方法去遍历dep数组并执行watcher的update方法去刷新视图。

3.Computed 和 Watch 的区别

computed

首先在init过程中会执行initProxy在渲染的时候获取getA会从vm实例中获取getA
在这里插入图片描述

我们再来看看computed的实现过程
在这里插入图片描述
我们进入watcher看看其中getter函数就是我们定义的computed函数getA。
在这里插入图片描述
在执行渲染函数的时候触发我们开头设置的proxy
在这里插入图片描述
createComputedGetter函数在init过程中定义
在这里插入图片描述
执行watcher的evaluate方法此时调用get方法该方法就是getA函数。
在这里插入图片描述
此时会触发变量的get方法去收集当前的Dep.target(computed的watcher实例)。所以当变量发生变化时会执行watcher的update方法。
在这里插入图片描述

缓存

computed还有缓存功能当依赖不发生变化时是不会重新执行的看如下代码dirty为false不会重新执行computed函数而是直接返回值。
在这里插入图片描述

不支持异步

从上面的分析可知会执行computed函数然后通知变量收集依赖如果是异步函数那么返回的就是一个Promise此时变量无法收集依赖所以不支持异步也很好解释。

watch

先看看实现过程首先watch也会实例化一个watcherhandler就是watcher函数。
在这里插入图片描述

支持异步监听

之所以支持异步是因为是根据获取函数名去监听的函数名是从变量中获取到的不涉及到函数内部实现所以函数内部是否异步并无关联。
在这里插入图片描述
通过执行watcher的get方法获取初始值
在这里插入图片描述
在这里插入图片描述

由于expOrFn是字符串所以会执行parsePath函数obj是vm对象从vm对象中获取变量的。在获取对象的值时变量会收集当前的watcher。

在这里插入图片描述
当变量改变时会触发watcher的update方法从而执行queneWatcher函数异步执行flushSchedulerQueue方法
在这里插入图片描述
这里又会执行watcher的run方法
在这里插入图片描述

不支持缓存

通过get方法获取变量的最新值通过判断当前值是否改变或者值是个对象或者有deep属性从而记录oldValue。然后调用用户定义的watch函数并传入新值和旧值在实现方法中并没有缓存这么一说因为没有返回值。
在这里插入图片描述
总结
相同点

  1. 初始化过程都会生成watcher实例。
  2. 监听的过程都是触发变量的get方法收集watcher实例

不同点

  1. computed会对结果缓存是因为有返回值 watch没有缓存是因为没有返回值。
  2. computed不支持异步因为要函数执行结果只能拿到promise无法触发变量的get方法watch支持异步因为不依赖函数内部实现

4. 说说once事件修饰符原理

带once和不带的区别是渲染的时候click函数不一样带once的是~click还有arguments参数和$event事件。
在这里插入图片描述
我们来看看怎么处理~click的在createElm的时候执行invokeCreateHooks
在这里插入图片描述
cbs.create对象中包含了updateDOMListeners函数
在这里插入图片描述
在这里插入图片描述
这里先执行normalizeEvent解析name
在这里插入图片描述
执行createOnceHandler返回onceHandler函数如果当前执行函数返回不是null则会移除该事件。
在这里插入图片描述
所以函数返回值为null时是不会移除监听事件的

在这里插入图片描述
总结
在render函数createEle的时候会通过addEventListener给当前dom添加事件once就是通过判断返回值是否为null来决定是否移除监听事件

5.说说v-show的原理

v-show时vue的内部指令会被解析为如下格式
在这里插入图片描述
createEle时调用如下函数
在这里插入图片描述

在这里插入图片描述
这里会执行updateDirectives函数的_update
在这里插入图片描述
这里执行了
在这里插入图片描述
在这里插入图片描述

在执行bind方法的时候会先获取当前的指令的value值然后根据该值设置是否设置当前el的display是否为none。

在这里插入图片描述
总结
v-show只是在创建el的时候通过获取判断条件的值去设置当前dom的display属性所以v-show不会影响到vnode的形成。

6.说下v-model的实现原理

1.在组件上的用法

从源码看vue(v2.7.10)中的v-model(双向绑定)之组件的原理

2.在表单上的用法

从源码看vue(v2.7.10)中的v-model(双向绑定)之input的原理

7.data为什么是一个函数而不是对象

在引用组件的时候如果data是一个对象的话那么就会出现多个对象指向同一个内存地址导致一处改变多个引用组件都会变化。所以只要返回的对象指向不同的内存地址即可不一定就要返回一个函数。
在这里插入图片描述

8.对keep-alive的理解它是如何实现的具体缓存的是什么

从源码看vue(v2.7.10)中的keep-alive的原理

未完待续持续更新。。。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: vue