共计 2490 个字符,预计需要花费 7 分钟才能阅读完成。
本文章转自:乐字节
文章次要解说: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 函数。
感激大家的认同与反对,小编会继续转发《乐字节》优质文章