Vue执行流程分析

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 相信绝大多数的前端小伙伴已记不清做了多少项目,写了多少代码了,每个人如同教科书般地写着Vue代码

引言


相信绝大多数的前端小伙伴已记不清做了多少项目,写了多少代码了,每个人如同教科书般地写着Vue代码:


// 单文件组件中常见代码
export default {
  data () {
    return {
      msg: 'click me'
    }
  },
  methods: {
    say () {
      this.msg = 'well done'
    }
  }
}


// 入口文件中的常见代码
new Vue({
  el: '#app',
  router: router,
  render: h => h(App)
})


一切都显得那么自然。不过在百忙之中是否有小伙伴想过,一个小小的Vue实例怎么有这么大的能量,竟然可以构建出如此复杂的前端项目。那么Vue内部是如何运转的呢,做了哪些事情呢,从今天开始跟着我一探究竟。


vue是可以运行在多平台上的如浏览器,weex等,本文只分析vue在浏览器环境下的主线执行流程。


初始化


我们先看一下Vue的构造函数:


// Vue构造函数
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)
}


从Vue的构造函数中可以看到,当我们执行new Vue()的时候,只执行了一个_init方法。_init会根据传入的选项对vue进行初始化。 props、data、生命周期,事件机制的初始化都是在此过程中完成的。


以data的初始化为例,vue会通过 Object.defineProperty 的方式将data的属性定义到vue实例上。这也就解释了为什么我们可以在vue中通过对 this.msg 进行赋值,可以修改data中属性的值了。


以上对data的处理只是刚刚开始。为了能实现所谓的响应式或者数据驱动更新,vue又做了进一步的处理,具体做法是,创建一个observer对象,该对象与data绑定,通过 Object.defineProperty 将data中的所有的属性转换成getter/setter。当data中的属性在vue实例中被访问(会触发getter),observer 对象就会把该属性收集为watcher实例的依赖,之后当data中的属性在vue实例中被改变(会触发setter), observer 会通知依赖该属性的 watcher 实例重新渲染页面。


注:每个watcher都对应一个vue实例


以上处理流程串在一起,vue就实现了通过修改 this.msg 从而触发页面的自动更新。

最后借用vue官网上的一张示意图帮助大家再理解下这个处理过程:


网络异常,图片无法展示
|


模板解析


通过上面的分析,我们已经知道当数据发生变化时,会触页面的重新渲染。接下来我们分析下vue是如何进行渲染的。


首先,vue会把将我们编写的HTML模板解析成一个AST描述对象,该对象是通过childrenparent链接而成的树形结构,完整地描述了HTML标签的所有信息。


例如有如下HTML模板:


<div id="app">
    <p>{{msg}}</p>
</div>


最终会解析成如下形式的AST对象:


{
   attrs: [{name: "id", value: ""app"", dynamic: undefined, start: 5, end: 13}],
   attrsList: [{name: "id", value: "app", start: 5, end: 13}],
   attrsMap: {id: "app"},
   children: [{
        attrsList: [],
        attrsMap: {},
        children: [],
        end: 33,
        parent: {type: 1, tag: "div", ...},
        plain: true,
        pre: undefined,
        rawAttrsMap:{},
        start: 19
        tag: "p",
        type: 1
   }],
   end: 263,
   parent: undefined,
   plain: false,
   rawAttrsMap:{id: {name: "id", value: "app", start: 5, end: 13}},
   start: 0
   tag: "div",
   type: 1
}


然后 vue 根据AST对象生成 render 函数,该函数的函数体大致如下:


with(this){
    return _c('div', {attrs:{"id":"app"}}, [_c('p', [_v(_s(msg))])])
}


也就是说,我们的模板最终在vue内部都是会以一个render函数的形式存在。


vue官网上对此也有提及,一般推荐大家使用template,el等方式来指定模板,此外还可以通过使用render来自定义个性化的编译函数,不过vue内部最终都会解析成render函数。


先虚后实


我们得到render函数之后,vue并未直接渲染成DOM树,而是先通过render函数得到一个vnode。实际上这一步是非常有必要的,我们都知道频繁大量地操作DOM节点是极耗性能的。vue在渲染之前通过对vnode的比较,可以大大规避非必要的DOM操作。下面是一个vnode大致结构:


{
    tag: "div",
    children: [{tag: "p", ...}],
    data: {attrs: {id: "app"}}
    elm: DOM节点(div#app),
    parent: undefined,
    context: Vue实例,
    ...
}


最后,vue根据diff之后的结果,执行真正的dom节点的插入更新删除等操作,同时触发vue实例的生命周期钩子函数。之后,vue要做的就是观察数据的变化,进而决定是否重新渲染页面了。


总结


以上就是vue在初始渲染过程中的主干流程,大体总结起来就是先对选项对象初始化,通过Object.defineProperty建立一套响应式系统,然后将模板解析成render函数,然后使用render函数生成vnode,在渲染前,对vnode进行diff操作,最后进行必要的渲染。


本文并未深入每个执行中的代码细节,接下来会详细对初始化、响应式实现原理、模板渲染、指令解析、vnode的diff等进行介绍,敬请期待。


相关文章
|
21天前
|
移动开发 JavaScript API
Vue Router 核心原理
Vue Router 是 Vue.js 的官方路由管理器,用于实现单页面应用(SPA)的路由功能。其核心原理包括路由配置、监听浏览器事件和组件渲染等。通过定义路径与组件的映射关系,Vue Router 将用户访问的路径与对应的组件关联,支持哈希和历史模式监听 URL 变化,确保页面导航时正确渲染组件。
|
25天前
|
监控 JavaScript 前端开发
ry-vue-flowable-xg:震撼来袭!这款基于 Vue 和 Flowable 的企业级工程项目管理项目,你绝不能错过
基于 Vue 和 Flowable 的企业级工程项目管理平台,免费开源且高度定制化。它覆盖投标管理、进度控制、财务核算等全流程需求,提供流程设计、部署、监控和任务管理等功能,适用于企业办公、生产制造、金融服务等多个场景,助力企业提升效率与竞争力。
83 12
|
21天前
|
JavaScript 前端开发 开发者
Vue中的class和style绑定
在 Vue 中,class 和 style 绑定是基于数据驱动视图的强大功能。通过 class 绑定,可以动态更新元素的 class 属性,支持对象和数组语法,适用于普通元素和组件。style 绑定则允许以对象或数组形式动态设置内联样式,Vue 会根据数据变化自动更新 DOM。
|
21天前
|
JavaScript 前端开发 数据安全/隐私保护
Vue Router 简介
Vue Router 是 Vue.js 官方的路由管理库,用于构建单页面应用(SPA)。它将不同页面映射到对应组件,支持嵌套路由、路由参数和导航守卫等功能,简化复杂前端应用的开发。主要特性包括路由映射、嵌套路由、路由参数、导航守卫和路由懒加载,提升性能和开发效率。安装命令:`npm install vue-router`。
|
2月前
|
JavaScript 安全 API
iframe嵌入页面实现免登录思路(以vue为例)
通过上述步骤,可以在Vue.js项目中通过 `iframe`实现不同应用间的免登录功能。利用Token传递和消息传递机制,可以确保安全、高效地在主应用和子应用间共享登录状态。这种方法在实际项目中具有广泛的应用前景,能够显著提升用户体验。
130 8
|
存储 前端开发 JavaScript
为什么我不再用Vue,改用React?
当我走进现代前端开发行业的时候,我做了一个每位开发人员都要做的决策:选择一个合适的框架。当时正逢 jQuery 被淘汰,前端开发者们不再用它编写难看的、非结构化的老式 JavaScript 程序了。
|
3月前
|
JavaScript
vue使用iconfont图标
vue使用iconfont图标
162 1
|
2月前
|
存储 设计模式 JavaScript
Vue 组件化开发:构建高质量应用的核心
本文深入探讨了 Vue.js 组件化开发的核心概念与最佳实践。
86 1
|
4月前
|
JavaScript 前端开发 开发者
vue 数据驱动视图
总之,Vue 数据驱动视图是一种先进的理念和技术,它为前端开发带来了巨大的便利和优势。通过理解和应用这一特性,开发者能够构建出更加动态、高效、用户体验良好的前端应用。在不断发展的前端领域中,数据驱动视图将继续发挥重要作用,推动着应用界面的不断创新和进化。
116 58
|
3月前
|
JavaScript 关系型数据库 MySQL
基于VUE的校园二手交易平台系统设计与实现毕业设计论文模板
基于Vue的校园二手交易平台是一款专为校园用户设计的在线交易系统,提供简洁高效、安全可靠的二手商品买卖环境。平台利用Vue框架的响应式数据绑定和组件化特性,实现用户友好的界面,方便商品浏览、发布与管理。该系统采用Node.js、MySQL及B/S架构,确保稳定性和多功能模块设计,涵盖管理员和用户功能模块,促进物品循环使用,降低开销,提升环保意识,助力绿色校园文化建设。

热门文章

最新文章