Vue 面试

响应式原理

function defineReactive(obj, key, val){
    Object.defineProperty(obj, key, {
        enumerable: true,       /* 属性可枚举 */
        configurable: true,     /* 属性可被修改或删除 */
        get: function reactiveGetter () {
            return val;         /* 实际上会依赖收集,下一小节会讲 */
        },
        set: function reactiveSetter (newVal) {
            if (newVal === val) return;
            cb(newVal);
        }
    });
}
function observer (value) {
    if (!value || (typeof value !== 'object')) {
        return;
    }
    
    Object.keys(value).forEach((key) => {
        defineReactive(value, key, value[key]);
    });
}

我们用observer来封装一个vue

这样我们只要new 一个对象, 就会将data中的数据进行“响应式”化

对于Object.defineProperty来说,处理对象和数组一样,只是在初始化时去改写get和set达到监测数组或对象的变化。对于新增的属性,需要手动再初始化。

依赖收集

依赖关系

订阅者Dep

观察者 watcher

进行依赖收集

Object.defineProperty 的 set/get 方法处理的事情,那么「依赖收集」的前提条件还有两个:

1.触发 get 方法; 2.新建一个 Watcher 对象

这个我们在 Vue 的构造类中处理。新建一个 Watcher 对象只需要 new 出来,这时候 Dep.target 已经指向了这个 new 出来的 Watcher 对象来。 而触发 get 方法也很简单,实际上只要把 render function 进行渲染,那么其中的依赖的对象都会被「读取」,这里我们通过打印来模拟这个过程,读取 test 来触发 get 进行「依赖收集」。

「依赖收集」的过程,配合之前的响应式原理,已经把整个「响应式系统」介绍完毕了。其主要就是 get 进行「依赖收集」。set 通过观察者来更新视图,配合下图仔细捋一捋,相信一定能搞懂它!

依赖

实现一个vnode

参数的解释 第一个是 标签, 第二是数据 是一个对象, 第三个是子节点的信息

创建空结点:

创建文本节点:

克隆一个vnode节点:

template 模版是怎样通过Compile编译的 compile 编译可以分成 parse、optimize 与 generate 三个阶段

parse 会用正则等方式将template模版中进行字符串解析,得到指令、class、style等数据,形成ast

parsehtml 首先我们需要定义个pasehtml函数,在里面我们循环解析template字符串

parseStartTag 用来解析起始标签

optimize

因为path的过程实际上是将vnode节点进行一层一层的比对,让后将“差异化”更新到视图上。

那么我们就需要为静态的节点做上一些「标记」,在 patch 的时候我们就可以直接跳过这些被标记的节点的比对,从而达到「优化」的目的。

isStatic

实现isStatic函数,传入一个node判断该node是否是静态节点。判断的标准是当type为2则是非静态节点,如果存在 if 或者 for这样的条件的时候(表达式节点),也是非静态节点。

markStatic

markStatic 为所有的节点标记上 static,遍历所有节点通过 isStatic 来判断当前节点是否是静态节点,此外,会遍历当前节点的所有子节点,如果子节点是非静态节点,那么当前节点也是非静态节点。

markStaticRoots

generate generate 会将 AST 转化成 render funtion 字符串,最终得到 render 的字符串以及 staticRenderFns 字符串

数据状态更新时的差异diff及patch机制

跨平台

vue 支持原生事件 和 dom 事件 platformModules createPatchFunction 的时候 遍历我们的hooks invokeCreateHook 时机

  1. 在createChildren

  2. 创建组件的时候

invokeUpdateHook

这两个都会执行 updateDomListeners 方法 判断: oldVnode 是不是都有on属性

最后更新于

这有帮助吗?