资讯专栏INFORMATION COLUMN

看一下从 new Vue()开始到页面看到真实dom都经历了什么?

hiyayiji / 3473人阅读

摘要:从开始看运行流程本篇文章不会具体分析很多每个方法内部具体逻辑,只为了研究一下浏览器加载文件后以及我后,都调用了哪些方法,这些方法都是做什么的等等。

从 new Vue()开始看vue运行流程

</>复制代码

  1. 本篇文章不会具体分析很多每个方法内部具体逻辑,只为了研究一下浏览器加载vuejs文件后以及我new Vue后,都调用了哪些方法,这些方法都是做什么的等等。以便对vue的执行流程有个大致了解,方便遇见问题排查是哪个过程出了问题。

用vue这么久我是很好奇从vue是怎么一步步把单文件组件的内容给渲染到空的div下面的,那从main.js入口开始,为了方便理解,我们只保留一个App.vue, main.js文件,路由,vuex,插件等等都不引入,在App.vue里面我们只定义一个data字段,插值绑定一个。

</>复制代码

  1. vue版本:2.5.2

先看下main.js,比较简单

</>复制代码

  1. import Vue from "vue";
  2. import App from "./App";
  3. Vue.config.productionTip = false;
  4. /* eslint-disable no-new */
  5. new Vue({
  6. el: "#app",
  7. render: h => h(App)
  8. });

下面开始分析具体调用了哪些方法

</>复制代码

  1. 分析过程会忽略一些辅助方法等无关的方法调用...

在new Vue之前也就是会做一些初始化的工作,列举部分重要的代码

</>复制代码

  1. /*
  2. initMixinVue.prototype添加:
  3. _init函数,
  4. ...
  5. */
  6. initMixin(Vue);
  7. /*
  8. stateMixinVue.prototype添加:
  9. $data属性,
  10. $props属性,
  11. $set函数,
  12. $delete函数,
  13. $watch函数,
  14. ...
  15. */
  16. stateMixin(Vue);
  17. /*
  18. eventsMixinVue.prototype添加:
  19. $on函数,
  20. $once函数,
  21. $off函数,
  22. $emit函数,
  23. $watch方法,
  24. ...
  25. */
  26. eventsMixin(Vue);
  27. /*
  28. lifecycleMixin给Vue.prototype添加:
  29. _update方法:私有方法,用于更新dom,其中调用_patch产生跟新后的dom,
  30. $forceUpdate函数,
  31. $destroy函数,
  32. ...
  33. */
  34. lifecycleMixin(Vue);
  35. /*
  36. renderMixin给Vue.prototype添加:
  37. $nextTick函数,
  38. _render函数,
  39. ...
  40. */
  41. renderMixin(Vue);

至此,部分常见的我们经常看到的初始化工作已经做完,现在我们知道我们在vm上用的$开头的方法都是在一加载vue.js完成后就挂在了Vue.prototype,我们的vm实例就可以用这些方法了。
下面当我们正式开始new Vue()

</>复制代码

  1. //调用this._init()
  2. new Vue(options);
  3. /*
  4. this._init函数
  5. 依次调用了跟vm相关的初始化函数:
  6. initLifecycle:给vm挂在一下属性
  7. $parent:undefined,
  8. $root:vm,
  9. $children:[],
  10. $refs:{},
  11. _isMounted:false,
  12. _isDestoryed:false,
  13. _watcher:null,
  14. ...
  15. initEvents:初始化事件.
  16. initRender:主要做了一下事情:
  17. 给vm添加_c函数和$createElement,其实是createElement别名,
  18. 给vm添加$attrs$listeners属性,$attrs & $listeners are exposed for easier HOC creation
  19. callHook(vm, "beforeCreate"):此时我们看到触发了beforeCreate钩子,此时的vm有哪些属性应该一目了然了.
  20. initInjections(vm): resolve injections before data/props,我们可以看到在初始化inject时还没有data和props
  21. initState:主要进行初始化:
  22. data:initData(vm),
  23. props:initProps(vm,opt.props)
  24. computed:initComputed(vm,opt.computed),
  25. methods:initMethods(vm,opt.methods),
  26. watch:initWatch(vm,opt.watch)
  27. initProvide:resolve provide,根据源码注释我们可以知道,在provide中可以使用props和data
  28. callHook(vm, "created"):此时生命周期created触发,我们能访问data,prop,provide等等
  29. 下面最后一步至关重要:
  30. if (vm.$options.el) {
  31. vm.$mount(vm.$options.el);
  32. }
  33. 这里是判断我们是否传入了el,属性,传入了则调用$mount方法挂载内容到el所在节点下
  34. */
  35. this._init(options)
  36. //在执行完 this._init() 后进入了最最重要的一步,挂载组件
  37. //程序接着往下走回执行:mountComponent
  38. /*
  39. 函数 mountComponent 主要做了下面这些事情:
  40. 触发 beforeMount() 钩子函数,
  41. 声明 updateComponent 函数,里面调用了 vm_update(vm._render(),...),这两个方法作用下面执行到的时候说一下.
  42. new Watcher(),此时会传入updateComponent函数,并随后执行此函数,执行后会发生一些函数执行,我只列举比较重要的大流程函数:
  43. Vue._render:执行由vue-loader生成的render函数或者自己写的render函数,最终返回一个由createComponent(非createPatchFunction内部的)产生的vnode.
  44. createComponent(非createPatchFunction内部):创建组件虚拟节点,此函数返回一个vnode,表示vue组件的vnode.
  45. vm._update:接收上面的vnode参数,这里面会触发VM.__patch__函数,这个函数里面最终返回的结果就是我们在html页面写的空的div,但是里面有了真实的内容,此时页面可以看到内容了,
  46. 触发 mount() 钩子函数,这个mount钩子每个组件实例会在自己的insert hook中调用
  47. */
  48. mountComponent()

到了这里,函数moutComponent执行完毕并且返回了vm,
this._init()执行完我们在页面就可以看到内容了

总结

我们可以大致总结一下从new Vue开始都大致执行了哪些重要的方法

</>复制代码

  1. 1.new Vue();
  2. 2.Vue.prototype._init();
  3. 3.Vue.prototype.$mount();
  4. 4.mountComponent();
  5. 5.new Watcher();
  6. 6.Watcher.prototype.get();
  7. 7.updateComponent();
  8. 8.Vue.prototype._render();
  9. 9.render();
  10. 10.createElement()
  11. 11.Vue.prototype._update();//这里面会执行vm.$el=vm.__patch__(),最终根vm的$el就有了真实dom值
  12. 12.Vue.prototype.__patch__();//这个应该是最重要的方法了,他返回了真实的dom节点。

vm.__patch__中会产生一个属于App.vue这个虚拟节点的实例,然后再次调用该实例的_init()方法,然后依次执行步骤2到12,继而完成app组件的挂载,最终new Vue出来的vm的$el,就是所有的真实dom。

在开始研究时在浏览器一步步调试看执行的过程,在谷歌的调试工具中借助这个call Stack

很方便查看运行过程都调用了哪些函数,在程序运行vm.__patch__后里面涉及到了这俩函数 createElm,createChilren互相调用的逻辑,然后由于在这之前又调用了几十个函数,导致调试到最后按F10电脑要卡顿好久才能进入下一步,我们看到页面可能是一瞬间的事情,但是vue帮我们做了很多事情,很感谢vue这么优秀的框架。

最后希望大家也去自己尝试下调试下源码,你会有新的发现!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95649.html

相关文章

  • vue源码阅读之数据渲染过程

    摘要:图在中应用三数据渲染过程数据绑定实现逻辑本节正式分析从到数据渲染到页面的过程,在中定义了一个的构造函数。一、概述 vue已是目前国内前端web端三分天下之一,也是工作中主要技术栈之一。在日常使用中知其然也好奇着所以然,因此尝试阅读vue源码并进行总结。本文旨在梳理初始化页面时data中的数据是如何渲染到页面上的。本文将带着这个疑问一点点追究vue的思路。总体来说vue模版渲染大致流程如图1所...

    AlphaGooo 评论0 收藏0
  • Vue原理】VNode - 源码版

    摘要:表示虚拟节点,为什么叫虚拟节点呢,因为不是真的节点。因为是对象,不管还是浏览器,都可以统一操作,从而获得了服务端渲染原生渲染手写渲染函数等能力减少操作。 写文章不容易,点个赞呗兄弟专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于 Vue版本 【2.5.17】 如果你觉得排版难看,请点击 下面链接 或者 拉到 下...

    layman 评论0 收藏0
  • 前端面试题大集合:来自真实大厂的532道面试题(只有题,没有答案)

    答案自己谷歌或百度找。 一、来源背景 面试题是来自微博@牛客网发布的真实大厂前端面经题目,我一直在收集题目长期一个一个的记录下来的,可能会有重复,但基本前端的面试大纲和需要掌握的知识都在其中了,面试题仅做学习参考,学习者阅后也要用心钻研其中的原理,重要知识需要系统学习、透彻学习,形成自己的知识链。 二、532道前端真实大厂面试题 express和koa的对比,两者中间件的原理,koa捕获异常多种情...

    Kerr1Gan 评论0 收藏0
  • 前端面试题大集合:来自真实大厂的532道面试题(只有题,没有答案)

    答案自己谷歌或百度找。 一、来源背景 面试题是来自微博@牛客网发布的真实大厂前端面经题目,我一直在收集题目长期一个一个的记录下来的,可能会有重复,但基本前端的面试大纲和需要掌握的知识都在其中了,面试题仅做学习参考,学习者阅后也要用心钻研其中的原理,重要知识需要系统学习、透彻学习,形成自己的知识链。 二、532道前端真实大厂面试题 express和koa的对比,两者中间件的原理,koa捕获异常多种情...

    lushan 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<