vue 源码解析之虚拟Dom-render

vue 源码解析 --虚拟Dom-render

instance/index.js
function Vue (options) {
 if (process.env.NODE_ENV !== 'production' &&
  !(this instanceof Vue)
 ) {
  warn('Vue is a constructor and should be called with the `new` keyword')
 }
 this._init(options)
}
renderMixin(Vue)

初始化先执行了 renderMixin 方法, Vue 实例化执行this._init, 执行this.init方法中有initRender()

renderMixin
installRenderHelpers( 将一些渲染的工具函数放在Vue 原型上)

Vue.prototype.$nextTick = function (fn: Function) {
  return nextTick(fn, this)
 }

仔细看这个函数, 在Vue中的官方文档上这样解释

Vue 异步执行 DOM 更新。只要观察到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作上非常重要。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部尝试对异步队列使用原生的 Promise.then MessageChannel,如果执行环境不支持,会采用 setTimeout(fn, 0)代替。

export function nextTick (cb?: Function, ctx?: Object) {
 let _resolve
 callbacks.push(() => {
  if (cb) {
   try {
    cb.call(ctx)
   } catch (e) {
    handleError(e, ctx, 'nextTick')
   }
  } else if (_resolve) {
   _resolve(ctx)
  }
 })
 if (!pending) {
  pending = true
  timerFunc()
 }
 // $flow-disable-line
 if (!cb && typeof Promise !== 'undefined') {
  return new Promise(resolve => {
   _resolve = resolve
  })
 }
}

Vue.nextTick用于延迟执行一段代码,它接受2个参数(回调函数和执行回调函数的上下文环境),如果没有提供回调函数,那么将返回promise对象。

function flushCallbacks () {
 pending = false
 const copies = callbacks.slice(0)
 callbacks.length = 0
 for (let i = 0; i < copies.length; i++) {
  copies[i]()
 }
}

这个flushCallbacks 是执行callbacks里存储的所有回调函数。

timerFunc 用来触发执行回调函数

先判断是否原生支持promise,如果支持,则利用promise来触发执行回调函数;
否则,如果支持MutationObserver,则实例化一个观察者对象,观察文本节点发生变化时,触发执行 
所有回调函数。

如果都不支持,则利用setTimeout设置延时为0。

const observer = new MutationObserver(flushCallbacks)
 const textNode = document.createTextNode(String(counter))
 observer.observe(textNode, {
  characterData: true
 })
 timerFunc = () => {
  counter = (counter + 1) % 2
  textNode.data = String(counter)
 }
 isUsingMicroTask = true

MutationObserver是一个构造器,接受一个callback参数,用来处理节点变化的回调函数,observe方法中options参数characterData:设置true,表示观察目标数据的改变

_render函数

通过执行 createElement 方法并返回的是 vnode,它是一个虚拟的 Node。

vnode = render.call(vm._renderProxy, vm.$createElement)

总结

以上所述是小编给大家介绍的vue 源码解析之虚拟Dom-render,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

(0)

相关推荐

  • Vue源码探究之虚拟节点的实现

    页面初始化的所有状态都准备就绪之后,下一步就是要生成组件相应的虚拟节点-- VNode .初次进行组件初始化的时候, VNode 也会执行一次初始化并存储这时创建好的虚拟节点对象.在随后的生命周期中,组件内的数据发生变动时,会先生成新的 VNode 对象,然后再根据与之前存储的旧虚拟节点的对比来执行刷新页面 DOM 的操作.页面刷新的流程大致上可以这样简单的总结,但是其实现路程是非常复杂的,为了深入地了解虚拟节点生成和更新的过程,首先来看看 VNode 类的具体实现. VNode 类 VNode

  • vue 虚拟dom的patch源码分析

    本文介绍了vue 虚拟dom的patch源码分析,分享给大家,具体如下: 源码目录:src/core/vdom/patch.js function updateChildren (parentElm, oldCh, newCh, insertedVnodeQueue, removeOnly) { let oldStartIdx = 0 let newStartIdx = 0 let oldEndIdx = oldCh.length - 1 let oldStartVnode = oldCh[0]

  • 浅谈vue的iview列表table render函数设置DOM属性值的方法

    如下所示: { title: '负责人社保照片', key: 'leaderIdNumber', render: (h, params) => { return h('img',{domProps:{ src:params.row.leaderIdNumber }}) } }, 找了好多,终于找到了原因,如果想要让列表返回的是一个img标签,并且设置img的src,这里不能用props,而是要用domProps就ok了. 以上这篇浅谈vue的iview列表table render函数设置DOM属

  • vue 源码解析之虚拟Dom-render

    vue 源码解析 --虚拟Dom-render instance/index.js function Vue (options) { if (process.env.NODE_ENV !== 'production' && !(this instanceof Vue) ) { warn('Vue is a constructor and should be called with the `new` keyword') } this._init(options) } renderMixin

  • Vue源码分析之虚拟DOM详解

    为什么需要虚拟dom? 虚拟DOM就是为了解决浏览器性能问题而被设计出来的.例如,若一次操作中有10次更新DOM的动作,虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到本地一个JS对象中,最终将这个JS对象一次性attch到DOM树上,再进行后续操作,避免大量无谓的计算量.简单来说,可以把Virtual DOM 理解为一个简单的JS对象,并且最少包含标签名( tag).属性(attrs)和子元素对象( children)三个属性. ----- 元素节点: 元素节点更贴近于我们

  • 从vue源码解析Vue.set()和this.$set()

    前言 最近死磕了一段时间vue源码,想想觉得还是要输出点东西,我们先来从Vue提供的Vue.set()和this.$set()这两个api看看它内部是怎么实现的. Vue.set()和this.$set()应用的场景 平时做项目的时候难免不会对 数组或者对象 进行这样的骚操作操作,结果发现,咦~~,他喵的,怎么页面没有重新渲染. const vueInstance = new Vue({ data: { arr: [1, 2], obj1: { a: 3 } } }); vueInstance.

  • Vue源码解析之Template转化为AST的实现方法

    什么是AST 在Vue的mount过程中,template会被编译成AST语法树,AST是指抽象语法树(abstract syntax tree或者缩写为AST),或者语法树(syntax tree),是源代码的抽象语法结构的树状表现形式. Virtual Dom Vue的一个厉害之处就是利用Virtual DOM模拟DOM对象树来优化DOM操作的一种技术或思路. Vue源码中虚拟DOM构建经历 template编译成AST语法树 -> 再转换为render函数 最终返回一个VNode(VNod

  • Vue源码解析之数组变异的实现

    力有不逮的对象 众所周知,在 Vue 中,直接修改对象属性的值无法触发响应式.当你直接修改了对象属性的值,你会发现,只有数据改了,但是页面内容并没有改变. 这是什么原因? 原因在于: Vue 的响应式系统是基于Object.defineProperty这个方法的,该方法可以监听对象中某个元素的获取或修改,经过了该方法处理的数据,我们称其为响应式数据.但是,该方法有一个很大的缺点,新增属性或者删除属性不会触发监听,举个栗子: var vm = new Vue({ data () { return

  • vue源码解析之事件机制原理

    上一章没什么经验.直接写了组件机制.感觉涉及到的东西非常的多,不是很方便讲.今天看了下vue的关于事件的机制.有一些些体会.写出来.大家一起纠正,分享.源码都是基于最新的Vue.js v2.3.0.下面我们来看看vue中的事件机制: 老样子还是先上一段贯穿全局的代码,常见的事件机制demo都会包含在这段代码中: <div id="app"> <div id="test1" @click="click1">click1<

  • Vue源码解析之数据响应系统的使用

    接下来重点来看Vue的数据响应系统.我看很多文章在讲数据响应的时候先用一个简单的例子介绍了数据双向绑定的思路,然后再看源码.这里也借鉴了这种方式,感觉这样的确更有利于理解. 数据双向绑定的思路 1. 对象 先来看元素是对象的情况.假设我们有一个对象和一个监测方法: const data = { a: 1 }; /** * exp[String, Function]: 被观测的字段 * fn[Function]: 被观测对象改变后执行的方法 */ function watch (exp, fn)

  • Vue $nextTick 为什么能获取到最新Dom源码解析

    目录 正文 修改数据之后 update 方法 nextTick 方法里面怎么执行传进去更新方法 正文 <template> <p id='text'>{{text}}</p> <button @click='change'>click</button> </template> <script> export default { data() { return { text: 'hello world' } } method

  • 深入解析vue 源码目录及构建过程分析

    ​" 本文主要梳理一下vue代码的目录,以及vue代码构建流程,旨在对vue源码整体有一个认知,有助于后续对源码的阅读." 一.目录结构 上图是对vue的代码的所有目录进行的梳理,其中源码位于src目录下,下面对src下的目录进行介绍. compiler 该目录是编译相关的代码,即将 template 模板转化成 render 函数的代码. vue 提供了 render 函数,render 函数作用是用来创建 VNode,但在平时开发中,绝大多数情况下使用 template 来创建 H

随机推荐