本文章转自:乐字节

文章次要解说:Vue实现原理

获取更多VUE相干材料及我的项目能够关注公众号《乐字节》 发送:999

1、Vue简介

当初的大前端时代,是一个动荡纷争的时代,江湖中曾经分成了很多门派,次要以Vue,React还有Angular为首,造成前端框架三足鼎立的局势。Vue在前端框架中的位置就像已经的jQuery,因为其简略易懂、开发效率高,曾经成为了前端工程师必不可少的技能之一。

Vue是一种渐进式JavaScript框架,完满交融了第三方插件和UI组件库,它和jQuery最大的区别在于,Vue无需开发人员间接操作DOM节点,就能够扭转页面渲染内容,在利用开发者具备肯定的HTML、CSS、JavaScript的根底上,可能疾速上手,开发出优雅、简洁的利用程序模块。

然而咱们提及Vue的时候,更多的是关注它的用法,而不是学习它是如何解决前端问题的,这多少有点亚健康。有前端开发教训的人,肯定在开发过程中遇到过奇奇怪怪的问题,而后稀里糊涂地解决,假使再次遇到类似的问题,便再次不知所措,作为一名前端工程师,在遇到问题的时候咱们是否能精确定位产生问题的起因并及时解决,次要取决于咱们对前端框架的了解是否足够深刻。

2、Vue实现原理

2.1 虚构DOM(Virtual DOM)

随着时代的倒退,Web利用的页面交互成果越来越简单,页面性能越来越丰盛,须要保护的状态越来越多,DOM操作也越来越频繁。DOM操作尽管简略易用,然而会产生不好保护的问题。

在程序执行的过程中,Watcher初始化时会将每一个节点和状态进行一一关联和映射,setter监听到Data的状态产生扭转后,就会告诉Watcher,Watcher会将这些变动告诉已经记录过的DOM以及跟这些状态相干的节点,从而触发页面的渲染过程。组件接管到状态变动后,会通过编译将模板转换成渲染函数Render,执行渲染函数就会失去一个虚构DOM树,通过比照旧的虚构DOM和新生成的虚构DOM树,来更新对应的理论DOM节点,执行页面渲染。

支流前端框架简直都在应用虚构DOM,然而在应用虚构DOM的时候,Angular和React都无奈确定具体是哪个状态产生了变动,因而须要在旧的虚构DOM和新的虚构DOM之间进行暴力比照,但Vue从1.0版本开始,就通过细粒度的绑定来更新视图,也就是说,当状态发生变化的时候Vue能够晓得具体是哪个状态哪些节点须要产生扭转,从而对这个节点执行更新,然而这种细粒度的变动侦测会有一些内存开销影响性能,一个我的项目越简单,开销就越大。

Vue从2.0版本后,为了优化性能,引入了虚构DOM,抉择了一个折中的计划,既不须要暴力比照整个新旧虚构DOM,也不须要通过细粒度的绑定来实现视图的更新,即以组件为单位进行Watcher监听,也就是说即使一个组件内有多个节点应用了某个状态,也只需一个Watcher来监听这个状态的变动,当这个状态发生变化时,Watcher告诉组件,组件外部通过虚构DOM的形式去进行节点的比照和从新渲染。

2.2 罕用指令实现原理

指令是指Vue提供的以“v-”前缀的个性,当指令中表达式的内容发生变化时,会连带影响DOM内容发生变化。Vue.directive全局API能够创立自定义指令,并获取全局指令,除了自定义指令,Vue还内置了一些开发过程中罕用的指令,如v-if、v-for等。在Vue模板解析时,会将指令解析到AST,应用AST生成字符串的过程中实现指令的性能。

在解析模板时,会将节点上的指令解析进去并增加到AST的directives属性中,directives将数据发送到VNode中,在虚构DOM进行页面渲染时,会触发某些钩子函数,当钩子函数被触发后,就阐明指令已失效。

2.2.1 v-if指令原理

在应用程序中应用v-if指令:

在编译阶段生成:

在代码执行时,会依据create的值来抉择创立哪个节点。

2.2.2 v-for指令原理

在应用程序中应用v-for指令:

在编译阶段生成:

_l是renderList的别名,执行代码时,_l函数会循环list变量,调用第二个参数中传递的函数,传递两个参数:item和index,当_c函数被调用时,会执行_v函数,创立一个节点。

2.2.3 自定义指令原理

在应用程序中,指令的解决逻辑别离监听了create函数、update函数以及destory函数,具体实现如下:

钩子函数被触发后,会执行updateDirectives函数,代码如下:

在该函数中,不管是否存在旧虚构节点,只有其中存在directives,就会执行_update函数,_update函数代码如下:

isCreate:判断该虚构节点是否是一个新建的节点。

isDistory:判断是否删除一个旧虚构节点。

oldDirs:旧的指令汇合,oldVnode中保留的指令。

newDirs:新的指令汇合,vnode中保留的指令。

dirsWithInsert:触发inserted指令钩子函数的指令列表。

dirsWithPostpatch:触发componentUpdated钩子函数的指令列表。

通过normalizeDirectives函数将模板中应用的指令从用户注册的自定义指令汇合中取出来的后果如下:

自定义指令的代码为:

虚构DOM在比照和渲染时,会依据不同情景触发不同的钩子函数,当应用虚构节点创立一个新的理论节点时,会触发create钩子函数,当一个DOM节点插入到父节点时,会触发insert钩子函数。

callHook函数执行钩子函数的形式如下:

callHook函数的参数意义别离为:

dir:指令对象。

hook:将要触发的钩子函数名。

vnode:新的虚构节点。

oldVnode:旧的虚构节点。

isDestory:判断是否删除一个旧虚构节点。

虚构DOM在渲染时会触发的所有钩子函数及其触发机制如下:

须要留神的是,remove函数是只有一个元素从其父元素中移除时才会触发,如果该元素是被移除元素的子元素,则不会触发remove函数。

感激大家的认同与反对,小编会继续转发《乐字节》优质文章