现代主流框架均使用一种数据=>视图的方式,隐藏了繁琐的dom操作,采用了声明式编程(Declarative Programming)替代了过去的类jquery的命令式编程(Imperative Programming)。
我一直找不到合适的语言来描述以上的观念,这句话的出现正中我心。
Maybe可以说Vue的学习可以分为四个阶段:
会使用基本的语法(大概半天就学会了)
可以使用一些更加复杂的特性(经历了大量的工作实践)
懂得vue的原理
读懂vue的源码,甚至还可以自己造一个vue
当然,可能我还在第二个阶段,第四个阶段也是我臆想的2333 当然也可以边看源码边学习原理的啊
现在我在看一些关于vue原理的东西,希望这篇文章可以记录我学到的知识和我的思考。
数据响应原理
这张图来自vue的官方文档,文档中讲:
当你把一个普通的 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。
这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。
每个组件实例都有相应的 watcher 实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。
在segmentfault的一篇文章Vue底层实现原理概述中有更详细的解析,可以总结为需要三个模块实现数据响应:
Observer:也就是vue官方文档第一段提到的使用Object.defineProperty监听数据变化,数据变化则触发setter,并通知订阅者Watcher。
Watcher:作为Observer和Compile之间通信的桥梁,在自身实例化时往属性订阅器(dep)里面添加自己,待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调。
Compile: 主要做的事情是解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图。
在CSDN上的另一篇文章从vue源码看观察者模式还可以对此作出补充:
这张图更好地解释了上文提到的Dep的作用,整个过程更加清晰。
总的来说,vue数据响应的核心是利用了 Object.defineProperty() 对数据进行劫持,并通过订阅,传递数据,最终进行update。
Virtual Dom
先放上一篇大牛的文章吧,很详细地讲解了vue virtual-dom的实现——Vue 2.0 的 virtual-dom 实现简析。
这里我只想说一下简单的原理和重要的流程。
首先要知道:
为什么使用virtual-dom?因为直接频繁地操作dom会有很高的性能消耗
为什么叫virtual-dom,实质是什么?顾名思义,虚拟dom,使用JS对象模拟dom进行操作(vue中叫做vnode)
整体流程是?
在上文讲到的进行update流程中,vue源码中的updateComponent函数执行后会返回新的vnode,然后将新的vnode和老的vnode进行diff,最后完成dom的更新工作。
然后我们再看一些流程中涉及的一些要素:
Vnode() 类:Vnode 是虚拟 DOM 节点类,其实例 vnode 是一个包含着渲染 DOM 节点所需要的一切信息的普通对象。
如何生成vnode?render() 方法根据当前 vm 的数据生成 vnode。
如何diff?简单来说,新老vnode基本属性相同时,进行diff(过程较复杂);新老vnode基本属性不同时,删除老的dom,新建新的真实dom。
如何更新真实dom?流程与diff过程交叉,利用了源码中重要的patch函数,生成真实dom更新视图。
我的笔记先记到这里啦,过后再进一步看源码肯定会有更深入的理解。
不对之处欢迎指正,想要更深入了解可以点进文章中的链接。
作者:李心doge
链接:https://www.jianshu.com/p/f5d6303a054a