vue首次渲染过程,响应式原理,虚拟 DOM 中 Key 的作用和好处

256 阅读4分钟

1、请简述 Vue 首次渲染的过程。

1. 首先 定义vue这个构造函数,在vue这个构造函数中调用init() 这个方法

2.  在 init 设置 isValue 为true的标记,在observe中判断是否是vue 实列,如果是实列不进行响应式处理

  2.·1 判断当前vue实列是否是组件 :如果是组件通过initInternalComponents() 方法,合并这些组件,如果不是会把我们传入测options和vue构造函数中options合并

  2.2  判断环境渲染的代理对象:

    2.2.1 . 开发环境 initProxy(vm):   先判断当前环境是否支持proxy对象,如果支持 通过new           Proxy代理vue实列,再赋给renderProxy ; 如果不支持就直接将vue实列(vm)赋给            renderProxy

     2.2.2.  生产环境 :就直接将vm 赋给 renderProxy

3. 给vue实列挂载一些成员

4.  调用mount(vm.mount(vm.options.el) 

    4.1  $mount 的核心作用是把模板编译成render函数

    4.2  获取options选项,再判断里面是否有render函数

         4.2.1 如果没有render 会去选中options里的template,再去判断template 是否存在,               如果存在,里面再去判断是否是字符串 (在去判断第一个字符是否有#,有的话就是id选               择器),或者是否有nodeType这个属性(有的话,直接返回template里的                               innerHTML)

         4.2.2 判断  是否有el 有的话,会获取el的outerHTML 作为template模板

         4.2.4 判断是否有template模板, 没有就直接报错,有的话就会通过compilToFunctions                   这个函数把template编译成render函数

5  最终调用mount方法渲染dom:

        5.1 内部会重新获取el(因为第4步是执行带编译时版本的vue,如果是运行时版本就不会                  执行上一个步骤,所以需要重新获取)

         5.2 定义mountComponent,判断是否有rander,里面再去判断是运行版本还是带编译                  的版本(编译版本会报错),如果有rander

                 5.2.1 会去调用berforeMount这个生命周期函数,

                 5.2.2 再通过updateComponent更新组件(挂载),给这个函数赋值(里面需要                           判断是否是开发环境,如果不是,调用vm.update(vm._render(),hydratiing)                       ---   _render()作用是调用用户传入的render或编译器生成的render,最终会返回                     虚拟dom,把虚拟dom传入给update 转换为真实的dom,更新到界面上)

           5.2.3 在watcher 调用mountComponent和get()

                get() : 创建完watcher会调用一次get

                          调用updateComponent()

                          调用vm.rendeer()创建VNode

                          调用vm,update(vnode...) 

           5.2.4 再通过callHook 调用vm中的mount生命周期函数

2、请简述 Vue 响应式原理。

在生成vue实例时,为对传入的data进行遍历,使用Object.defineProperty把这些属性转为getter/setter.

Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。

每个vue实例都有一个watcher实例,它会在实例渲染时记录这些属性,并在setter触发时重新渲染

Vue 无法检测到对象属性的添加或删除

Vue 不允许动态添加根级别的响应式属性。但是,可以使用 Vue.set(object, propertyName, value)方法向嵌套对象添加响应式属性

3、请简述虚拟 DOM 中 Key 的作用和好处。

由于在浏览器中操作DOM是很昂贵的。频繁的操作DOM,会产生一定的性能问题。这就是虚拟Dom的产生原因

Virtual DOM本质就是用一个原生的JS对象去描述一个DOM节点。是对真实DOM的一层抽象。(也就是源码中的VNode类,它定义在src/core/vdom/vnode.js中。)

key 是为 Vue 中 vnode 的唯一标记,通过这个 key,我们的 diff 操作可以更准确、更快速

4、请简述 Vue 中模板编译

Vue中模版的编译是如下过程:模版--->ast(抽象树)-->render 函数->虚拟 dom->实际 dom。

vue中的模版通过 compiler 编译成ast(用于表示模版的 js 对象,也可以说ast就是一个用来表示源代码的js对象),然后将ast生成对应render函数(这里先不谈关于ast的转化细节),render函数然后生成虚拟节点 vnode(用来描述节点及其子节点的信息),vnode的集合组成Virtual Dom(vue组件建立起来的整个vnode树叫虚拟Dom树),最后生成真实Dom。