Vue渲染原理
现在基本所有的框架都已经认同这个看法——DOM应尽可能是一个函数式到状态的映射。状态即是唯一的真相,而DOM状态只是数据状态的一个映射。如下图所示,所有的逻辑尽可能在状态的层面去进行,当状态改变的时候,View应该是在框架帮助下自动更新到合理的状态,而不是说当你观测到数据变化之后手动选择一个元素,再命令式地去改动它的属性。
下图是Vue的一个模板示例,如果没有用过Vue的话,可以大概感觉到这是一个怎样的概念。
其实,在模板语法上,Vue跟Angular是比较相似。在Vue1.0里面,模板实现跟Angular类似,如下图所示,把模板直接做成在浏览器里面parse成DOM树,然后去遍历这个树,提取其中的各种绑定。
在Vue2.0中,渲染层的实现做了根本性改动,那就是引入了虚拟DOM。
从架构来讲,Vue2.0 依然是写一样的模板,(Vue2.0于前段时间发布,具体报道:更轻更快的Vue.js 2.0)。在最左边,Vue2.0跟1.0的模板语法绝大部分是兼容的。Vue的编译器在编译模板之后,会把这些模板编译成一个渲染函数。而函数被调用的时候就会渲染并且返回一个虚拟DOM的树。这个树非常轻量,它的职责就是描述当前界面所应处的状态。当我们有了这个虚拟的树之后,再交给一个patch函数,负责把这些虚拟DOM真正施加到真实的DOM上。在这个过程中,Vue有自身的响应式系统来侦测在渲染过程中所依赖到的数据来源。在渲染过程中,侦测到的数据来源之后,之后就可以精确感知数据源的变动。到时候就可以根据需要重新进行渲染。当重新进行渲染之后,会生成一个新的树,将新树与旧树进行对比,就可以最终得出应施加到真实DOM上的改动。最后再通过patch函数施加改动。
这样做的主要原因是,在浏览器当中,JavaScript的运算在现代的引擎中非常快,但DOM本身是非常缓慢的东西。当你调用原生DOM API的时候,浏览器需要在JavaScript引擎的语境下去接触原生的DOM的实现,这个过程有相当的性能损耗。所以,本质的考量是,要把耗费时间的操作尽量放在纯粹的计算中去做,保证最后计算出来的需要实际接触真实DOM的操作是最少的。
下面看渲染函数。用过React的开发者可能知道,React是没有模板的,直接就是一个渲染函数,它中间返回的就是一个虚拟DOM树。JSX实际就是一套用于让我们更简单地去描述树状结构的语法糖。
如下图所示,在Vue2.0当中,可以看到就是说当比如左侧的模板,经过Vue的编译之后就会变成右侧的东西。
这个函数类似于创建一个虚拟元素的函数,我们可以给它一个名字,给它描述应该有的属性特性和可能其他的数据。然后后面这个最后这个参数是个数组,包含了该虚拟元素的子元素。总的来说2.0的编译器做的就是这个活。
同时,在Vue2.0里,用户可以选择直接跳过模板这一层去手写渲染函数,同时也有可选JSX支持。从开发者的偏好以及开发者的效益的角度来考量,模板和JSX是各有利弊的东西。模板更贴近我们的HTML,可以让我们更直观地思考语义结构,更好地结合CSS的书写。JSX和直接渲染函数,因为是真正的JavaScript,拥有这个语言本身的所有的能力,可以进行复杂的逻辑判断,进行选择性的返回最终要返回的DOM结构,能够实现一些在模板的语法限制下,很难做到的一些事情。
所以在Vue2.0里,两个都是可以选择的。在绝大部分情况下使用模板,但是在需要复杂逻辑的情况下,使用渲染函数。在Vue2.0的路由和内部的一些实践上,都大量地应用渲染函数做复杂的抽象组件,比如过渡动画组件以及路由里面的link组件,都是用渲染函数实现的,同时还保留了它本身的依赖追踪系统。
如下图所示,Vue的依赖追踪通过ES5的 Object.defineProperty 方法实现。比如,我们给它一个原生对象,Vue会遍历这个数据对象的属性,然后进行属性转换。每一个属性会被转换为一个 getter 和一个 setter。同时每个组件会有一个对应的 watcher 对象,这个对象的职责就是在当前组件被渲染的时候,记录数据上面的哪些属性被用到了。
例如,在渲染函数里面用到A.B的时候,这个就会触发对应的 getter。整个渲染流程具体要点如下:
当某个数据属性被用到时,触发 getter,这个属性就会被作为依赖被 watcher 记录下来。
整个函数被渲染完的时候,每一个被用到的数据属性都会被记录。
相应的数据变动时,例如给它一个新的值,就会触发 setter,通知数据对象对应数据有变化。
此时会通知对应的组件,其数据依赖有所改动,需要重新渲染。
对应的组件再次调动渲染函数,生成 Virtual DOM,实现 DOM 更新。
这样一个流程跟主流的一些框架,例如React是有较大区别的。在React中,当组件复杂的时候需要用 shouldComponentUpdate 做优化。但是,它也有自己的各种坑,比如要确保该组件下面的组件不依赖外部的状态。虽说这在大部分情况下是够用的,但遇到极大复杂度的应用,遇到性能瓶颈的时候,这个流程优化起来也是相当复杂的一个话题。
如下图所示,在Vue里面由于依赖追踪系统的存在,当任意数据变动的时,Vue的每一个组件都精确地知道自己是否需要重绘,所以并不需要手动优化。用Vue渲染这些组件的时候,数据变了,对应的组件基本上去除了手动优化的必要性。
Vue渲染原理的更多相关文章
- React / Vue 跨端渲染原理与实现探讨
跨端渲染是渲染层并不局限在浏览器 DOM 和移动端的原生 UI 控件,连静态文件乃至虚拟现实等环境,都可以是你的渲染层.这并不只是个美好的愿景,在今天,除了 React 社区到 .docx / .pd ...
- Vue渲染函数
前面的话 Vue 推荐在绝大多数情况下使用 template 来创建HTML.然而在一些场景中,真的需要 JavaScript 的完全编程的能力,这就是 render 函数,它比 template 更 ...
- vue 编译原理 简介
来源 tinycompile 关于vue的内部原理其实有很多个重要的部分,变化侦测,模板编译,virtualDOM,整体运行流程等. 之前写过一篇<深入浅出 - vue变化侦测原理> 讲了 ...
- Vue渲染数据理解以及Vue指令
一.Vue渲染数据原理 原生JS改变页面数据,必须要获取页面节点,也即是进行DOM操作,jQuery之类的框架只是简化DOM操作的写法,实质并没有改变操作页面数据的底层原理,DOM操作影响性能(导致浏 ...
- vue运行原理
Vue工作原理小结 本文能帮你做什么? 1.了解vue的双向数据绑定原理以及核心代码模块 2.缓解好奇心的同时了解如何实现双向绑定 为了便于说明原理与实现,本文相关代码主要摘自vue源码, 并进行了简 ...
- framework7的改进,以及与vue组合使用遇到的问题以及解决方法 (附vue的原理)
framework7官方提供了vue+framework7的组合包,但是那个包用起来复杂度较高,而且不灵活.听说bug也不少. 所以我想用最原始的方式单独使用vue和framework7. 遇到以下问 ...
- vue第六单元(vue的实例和组件-vue实例的相关属性和方法-解释vue的原理-创建vue的组件)
第六单元(vue的实例和组件-vue实例的相关属性和方法-解释vue的原理-创建vue的组件) #课程目标 掌握vue实例的相关属性和方法的含义和使用 了解vue的数据响应原理 熟悉创建组件,了解全局 ...
- FinClip 前端之 VUE 核心原理总结
小程序框架有很多,都是支持前端JavaScript语言的,也是支持 vue.js 框架的.FinClip 小程序是兼容各家平台的.所以在学习了框架使用之后的进阶就要熟悉框架的底层原理. 1.数据响应式 ...
- 【Web动画】CSS3 3D 行星运转 && 浏览器渲染原理
承接上一篇:[CSS3进阶]酷炫的3D旋转透视 . 最近入坑 Web 动画,所以把自己的学习过程记录一下分享给大家. CSS3 3D 行星运转 demo 页面请戳:Demo.(建议使用Chrome打开 ...
随机推荐
- .net mvc4 + ajaxfileupload.js 解决IE浏览器中弹出下载对话框问题
摘要:每一个人遇到的问题都不一样,在网上找了一大圈都没有解决到我的问题!由于我的环境如标题所看到的.攻克了这个问题. 主要问题:在于响应头的设置 Controller: [HttpPost] publ ...
- [DevExpress]GridControl分页的实现
加入两个组件:BindingNavigator和BindingSource 代码: using System; using System.Collections.Generic; using Syst ...
- 2016/1/14 java生成指定范围的随机数
java生成指定范围的随机数 package edu.sjtu.erplab.io; import java.util.Random; public class RandomTest { public ...
- hibernate 下载
https://sourceforge.net/projects/hibernate/files/hibernate-orm/5.0.7.Final/ http://sourceforge.net/p ...
- HDU 5753Permutation Bo
Permutation Bo Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) ...
- xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is
method: select Xcode version in Command Line Tools in Location(Click Xcode and then Preferences) Bef ...
- [Codeforces 986E] Prince's Problem
[题目链接] https://codeforces.com/contest/986/problem/E [算法] X到Y的路径积 , 可以转化为X到根的路径积乘Y到根的路径积 , 除以LCA到根的路径 ...
- Rails5 Model Document
创建: 2017/06/09 更新: 2017/06/21 更新: 2017/06/23 对待未完成的追加# TODO: 更新: 2017/06/29 修正文件名db/seed.rb ---> ...
- bzoj 2427: [HAOI2010]软件安装【tarjan+树形dp】
一眼最大权闭合子图,然后开始构图,画了画之后发现我其实是个智障网络流满足不了m,于是发现正确的打开方式应该是一眼树上dp 然后仔细看了看性质,发现把依赖关系建成图之后是个奇环森林,这个显然不能直接dp ...
- bzoj 1700: [Usaco2007 Jan]Problem Solving 解题【dp】
很像贪心的dp啊 这个定金尾款的设定让我想起了lolita和jk制服的尾款地狱-- 设f[i][j]为从j到i的付定金的最早月份然后从f[k][j-1]转移来,两种转移f[i][j]=min(f[i] ...