每一个 Vue 应用都是经过用 Vue 函数建立一个新的 Vue 实例开始的:vue
var vm = new Vue({
// 选项
})
复制代码
一个 Vue 应用由一个经过 new Vue 建立的根 Vue 实例,以及可选的嵌套的、可复用的组件树组成。当一个 Vue 实例被建立时,它将 data 对象中的全部的属性加入到 Vue 的响应式系统中。当这些属性的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。当这些数据改变时,视图会进行重渲染。node
在 new Vue() 以后。 Vue 会调用 _init 函数进行初始化,也就是这里的 init 过程,它会初始化生命周期、事件、 props、 methods、 data、 computed 与 watch 等。其中最重要的是经过 Object.defineProperty 设置 setter 与 getter 函数,用来实现「响应式」以及「依赖收集」。算法
compile编译能够分红 parse、optimize 与 generate 三个阶段,最终须要获得 render function。数组
在经历过 parse、optimize 与 generate 这三个阶段之后,组件中就会存在渲染 VNode 所需的 render function 了浏览器
当 render function 被渲染的时候,由于会读取所需对象的值,因此会触发 getter 函数进行「依赖收集」,「依赖收集」的目的是将观察者 Watcher 对象存放到当前闭包中的订阅者 Dep 的 subs 中。造成以下所示的这样一个关系。bash
render function 会被转化成 VNode 节点。Virtual DOM 其实就是一棵以 JavaScript 对象( VNode 节点)做为基础的树,用对象属性来描述节点,实际上它只是一层对真实 DOM 的抽象。最终能够经过一系列操做使这棵树映射到真实环境上。因为 Virtual DOM 是以 JavaScript 对象为基础而不依赖真实平台环境,因此使它具备了跨平台的能力,好比说浏览器平台、Weex、Node 等。闭包
{
tag: 'div', /*说明这是一个div标签*/
children: [ /*存放该标签的子节点*/
{
tag: 'a', /*说明这是一个a标签*/
text: 'click me' /*标签的内容*/
}
]
}
复制代码
渲染后能够获得dom
<div>
<a>click me</a>
</div>
复制代码
当数据变化后,执行 render function 就能够获得一个新的 VNode 节点,咱们若是想要获得新的视图,最简单粗暴的方法就是直接解析这个新的 VNode 节点,而后用 innerHTML 直接所有渲染到真实 DOM 中。可是其实咱们只对其中的一小块内容进行了修改,这样作彷佛有些「浪费」。异步
那么咱们为何不能只修改那些 「改变了的地方」 呢?这个时候就要介绍咱们的「patch」了。咱们会将新的 VNode 与旧的 VNode 一块儿传入 patch 进行比较,通过 diff 算法得出它们的 「差别」 。最后咱们只须要将这些 「差别」 的对应 DOM 进行修改便可。函数
事实上。vue2并无实现节点上vdom更新,在vue3上才有望实现(2019vueconf大会尤雨奚)
new vue 初始化-mounted挂载-compile-render-createElement虚拟节点-(返回普通vnode或者createcomponents建立一个组件vnode,这个节点是vue的一个子类,总之返回的都是vnode,这个vnode可能有若干个子节点,它们也是vnode类型,这里就能够描述为vnode-tree)-update->patch(createElm做用是,若是vnode是普通的节点就建立真实的dom节点插入父元素下,若是节点vnode 的tag标明是组件,根据vnode建立一个组件节点,而且执行相应的钩子函数,这个过程就是遍历全部的子vnode,若是它的子节点vnode又是个组件,重复刚才的过程render-建立虚拟节点,这个过程是一个深度优先遍历的算法。