Vue使用虚拟dom进行渲染view的方法
前端  /  管理员 发布于 5年前   522
前提 vue版本:v2.5.17-beta.0 触发render vue在数据更新后会自动触发view的render工作,其依赖于数据驱动;在数据驱动的工作下,每一个vue的data属性都被监听,并且在set触发时,派发事件,通知收集到的依赖,从而触发对应的操作,render工作就是其中的一个依赖,并且被每一个data属性所收集,因此每一个data属性改变后,都会触发render。 vue更新监听 看一段代码 updateComponent是更新组件的函数,内部调用vm._update,并且传参vm._render(); 更新view 阅读_update函数得知,最终调用了vm.__patch__方法,最终找到为createPatchFunction方法的返回值 接下来重点看createPatchFunction的返回函数patch. 如果新的vnode不存在,则注销旧的vnode 如果旧的vnode不存在,则创建新的vnode 如果以上不成立,则新的vnode和oldVnode都存在.如果oldVnode不是真实的dom,则为虚拟dom节点,并且新老vnode相似,则进行diff算法 如果新老vnode不同,则拿到oldVnode的父节点,辅助创建vnode的新节点 以上的步骤发现,更新view时,重点进入到了patchVnode函数,因此下面进入patchVnode的函数阅读 如果新老node相等,则不做处理 如果vnode不是文本节点则有几种情况 如果vnode是文本节点, 则当新老节点文本不同,将dom的文本更新成新vnode的文本 patchVnode函数处理的情况梳理一下则为: 在patchVnode部分又浮现了一个新的函数:updateChildren,是在新老vnode都不是文本节点时调用的,这里就是vue的渲染机制的核心 updateChildren updateChildren中将新老vnode的children进行的循环处理,每一次循环去判断是否有相同的vnode,如果没有则查找当前新vnode的子节点的key是否存在oldVnode的children中,如果不存在在这存在但已经不相同则创建新的dom,否则,如果是新老节点相同,回调patchVnode函数去处理2个节点。 这样进行了递归处理,组件层的更新就完成了。 结尾 本文为看源码分析vue更新机制部分,省略了特殊场景的源码分析,比如ssr、静态组件等。 总结 以上所述是小编给大家介绍的Vue使用虚拟dom进行渲染view的方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对站的支持!// 来自mountComponent函数updateComponent = function () { vm._update(vm._render(), hydrating);};new Watcher(vm, updateComponent, noop, { before: function before () { if (vm._isMounted) { callHook(vm, 'beforeUpdate'); } }}, true /* isRenderWatcher */);
var patch = createPatchFunction({ nodeOps: nodeOps, modules: modules });Vue.prototype.__patch__ = inBrowser ? patch : noop;
if (isUndef(vnode)) { if (isDef(oldVnode)) { invokeDestroyHook(oldVnode); } return}
if (isUndef(oldVnode)) { // empty mount (likely as component), create new root element isInitialPatch = true; createElm(vnode, insertedVnodeQueue);}
var isRealElement = isDef(oldVnode.nodeType);if (!isRealElement && sameVnode(oldVnode, vnode)) { // patch existing root node patchVnode(oldVnode, vnode, insertedVnodeQueue, removeOnly);}
var oldElm = oldVnode.elm;var parentElm = nodeOps.parentNode(oldElm);// create new nodecreateElm( vnode, insertedVnodeQueue, // extremely rare edge case: do not insert if old element is in a // leaving transition. Only happens when combining transition + // keep-alive + HOCs. (#4590) oldElm._leaveCb ? null : parentElm, nodeOps.nextSibling(oldElm));
if (oldVnode === vnode) { return}
if (isDef(oldCh) && isDef(ch)) { // 如果oldVnode和vnode的children都有值(组件层),并且不想等,则执行更新children流程 if (oldCh !== ch) { updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly); }} else if (isDef(ch)) { // 如果vnode的children有值,如果当前dom有文本则清空, // 并将oldVnode的dom作为父节点,创建新vnode的children节点 if (isDef(oldVnode.text)) { nodeOps.setTextContent(elm, ''); } addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue);} else if (isDef(oldCh)) { // 如果oldVnode存在children,但是新的没有,则删除oldVnode的children的vnode removeVnodes(elm, oldCh, 0, oldCh.length - 1);} else if (isDef(oldVnode.text)) { // 如果oldVnode有文本信息,则将dom的文本清空 nodeOps.setTextContent(elm, '');}
else if (oldVnode.text !== vnode.text) { nodeOps.setTextContent(elm, vnode.text);}
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!您可能感兴趣的文章:
123 在
Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..原梓番博客 在
在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..博主 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..1111 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..路人 在
php中使用hyperf框架调用讯飞星火大模型实现国内版chatgpt功能示例中评论 教程很详细,如果加个前端chatgpt对话页面就完美了..
Copyright·© 2019 侯体宗版权所有·
粤ICP备20027696号