网站建设明细报价表模板,广西房管局官网,网站后台编辑不了,手机销售网站源码Vue.js通过编译将template 模板转换成渲染函数(render ) #xff0c;执行渲染函数就可以得到一个虚拟节点树在对 Model 进行操作的时候#xff0c;会触发对应 Dep 中的 Watcher 对象。Watcher 对象会调用对应的 update 来修改视图。这个过程主要是将新旧虚拟节点进行差异对比… Vue.js通过编译将template 模板转换成渲染函数(render ) 执行渲染函数就可以得到一个虚拟节点树在对 Model 进行操作的时候会触发对应 Dep 中的 Watcher 对象。Watcher 对象会调用对应的 update 来修改视图。这个过程主要是将新旧虚拟节点进行差异对比然后根据对比结果进行DOM操作来更新视图。 简单点讲在Vue的底层实现上Vue将模板编译成虚拟DOM渲染函数。结合Vue自带的响应系统在状态改变时Vue能够智能地计算出重新渲染组件的最小代价并应到DOM操作上。 patch(也叫做patching算法)虚拟DOM最核心的部分它可以将vnode渲染成真实的DOM这个过程是对比新旧虚拟节点之间有哪些不同然后根据对比结果找出需要更新的的节点进行更新。这点我们从单词含义就可以看出 patch本身就有补丁、修补的意思其实际作用是在现有DOM上进行修改来实现更新视图的目的。Vue的Virtual DOM Patching算法是基于Snabbdom的实现并在些基础上作了很多的调整和改进 Virtual DOM 其实就是一棵以 JavaScript 对象( VNode 节点)作为基础的树用对象属性来描述节点实际上它只是一层对真实 DOM 的抽象。最终可以通过一系列操作使这棵树映射到真实环境上。 虚拟DOM的最终目标是将虚拟节点渲染到视图上。但是如果直接使用虚拟节点覆盖旧节点的话会有很多不必要的DOM操作。例如一个ul标签下很多个li标签其中只有一个li有变化这种情况下如果使用新的ul去替代旧的ul,因为这些不必要的DOM操作而造成了性能上的浪费。 为了避免不必要的DOM操作虚拟DOM在虚拟节点映射到视图的过程中将虚拟节点与上一次渲染视图所使用的旧虚拟节点oldVnode做对比找出真正需要更新的节点来进行DOM操作从而避免操作其他无需改动的DOM。 其实虚拟DOM在Vue.js主要做了两件事 提供与真实DOM节点所对应的虚拟节点vnode将虚拟节点vnode和旧虚拟节点oldVnode进行对比然后更新视图具备跨平台的优势由于 Virtual DOM 是以 JavaScript 对象为基础而不依赖真实平台环境所以使它具有了跨平台的能力比如说浏览器平台、Weex、Node 等。 操作 DOM 慢js运行效率高。我们可以将DOM对比操作放在JS层提高效率。因为DOM操作的执行速度远不如Javascript的运算速度快因此把大量的DOM操作搬运到Javascript中运用patching算法来计算出真正需要更新的节点最大限度地减少DOM操作从而显著提高性能。 Virtual DOM 本质上就是在 JS 和 DOM 之间做了一个缓存。可以类比 CPU 和硬盘既然硬盘这么慢我们就在它们之间加个缓存既然 DOM 这么慢我们就在它们 JS 和 DOM 之间加个缓存。CPUJS只操作内存Virtual DOM最后的时候再把变更写入硬盘DOM 提升渲染性能Virtual DOM的优势不在于单次的操作而是在大量、频繁的数据更新下能够对视图进行合理、高效的更新。 为了实现高效的DOM操作一套高效的虚拟DOM diff算法显得很有必要。我们通过patch 的核心----diff 算法找出本次DOM需要更新的节点来更新其他的不更新。 Vue的diff算法是基于snabbdom改造过来的仅在同级的vnode间做diff递归地进行同级vnode的diff最终实现整个DOM树的更新。因为跨层级的操作是非常少的忽略不计这样时间复杂度就从O(n3)变成O(n)。 diff 算法的实现过程 diff 算法本身非常复杂实现难度很大。本文去繁就简粗略介绍以下两个核心函数实现流程 patch(container,vnode) :初次渲染的时候将VDOM渲染成真正的DOM然后插入到容器里面。patch(vnode,newVnode):再次渲染的时候将新的vnode和旧的vnode相对比然后之间差异应用到所构建的真正的DOM树上。function createElement(vnode) {
var tag vnode.tag
var attrs vnode.attrs || {}
var children vnode.children || []
if (!tag) { return null }
// 创建真实的 DOM 元素
var elem document.createElement(tag) // 属性
var attrName
for (attrName in attrs) { if (attrs.hasOwnProperty(attrName)) { // 给 elem 添加属性elem.setAttribute(attrName, attrs[attrName])}}// 子元素children.forEach(function (childVnode) {// 给 elem 添加子元素如果还有子节点则递归的生成子节点。elem.appendChild(createElement(childVnode)) // 递归}) // 返回真实的 DOM 元素 return elem
} 2.patch(vnode,newVnode) 这里我们只考虑vnode与newVnode如何对比的情况 function updateChildren(vnode, newVnode) {var children vnode.children || []var newChildren newVnode.children || []// 遍历现有的childrenchildren.forEach(function (childVnode, index) {var newChildVnode newChildren[index]// 两者tag一样if (childVnode.tag newChildVnode.tag) {// 深层次对比递归updateChildren(childVnode, newChildVnode)} else { // 两者tag不一样replaceNode(childVnode, newChildVnode) }}
)} 转载于:https://www.cnblogs.com/zhouyideboke/p/11208638.html