前提
vue版本:v2.5.17-beta.0
触发render
vue在数据更新后会自动触发view的render工作,其依赖于数据驱动;在数据驱动的工作下,每一个vue的data属性都被监听,并且在set触发时,派发事件,通知收集到的依赖,从而触发对应的操作,render工作就是其中的一个依赖,并且被每一个data属性所收集,因此每一个data属性改变后,都会触发render。
vue更新监听
看一段代码
// 来自mountComponent函数 updateComponent = function () { vm._update(vm._render(), hydrating); }; new Watcher(vm, updateComponent, noop, { before: function before () { if (vm._isMounted) { callHook(vm, 'beforeUpdate'); } } }, true /* isRenderWatcher */);
updateComponent是更新组件的函数,内部调用vm._update,并且传参vm._render();
- vm._render()返回了什么?看源码则得知返回了虚拟dom(VNode)
- vm._update函数又做了什么事情?顾名思义,更新传入的vnode
- 什么时候触发updateComponent函数?在任何vue的data属性更改值都会触发
更新view
阅读_update函数得知,最终调用了vm.__patch__方法,最终找到为createPatchFunction方法的返回值
var patch = createPatchFunction({ nodeOps: nodeOps, modules: modules }); Vue.prototype.__patch__ = inBrowser "htmlcode">if (isUndef(vnode)) { if (isDef(oldVnode)) { invokeDestroyHook(oldVnode); } return }如果旧的vnode不存在,则创建新的vnode
if (isUndef(oldVnode)) { // empty mount (likely as component), create new root element isInitialPatch = true; createElm(vnode, insertedVnodeQueue); }如果以上不成立,则新的vnode和oldVnode都存在.如果oldVnode不是真实的dom,则为虚拟dom节点,并且新老vnode相似,则进行diff算法
var isRealElement = isDef(oldVnode.nodeType); if (!isRealElement && sameVnode(oldVnode, vnode)) { // patch existing root node patchVnode(oldVnode, vnode, insertedVnodeQueue, removeOnly); }如果新老vnode不同,则拿到oldVnode的父节点,辅助创建vnode的新节点
var oldElm = oldVnode.elm; var parentElm = nodeOps.parentNode(oldElm); // create new node createElm( 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 "htmlcode">if (oldVnode === vnode) { return }如果vnode不是文本节点则有几种情况
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, ''); }如果vnode是文本节点, 则当新老节点文本不同,将dom的文本更新成新vnode的文本
else if (oldVnode.text !== vnode.text) { nodeOps.setTextContent(elm, vnode.text); }patchVnode函数处理的情况梳理一下则为:
- 如果新老vnode相同,不作处理
- 如果新vnode是文本节点,并且新老文本不同,将dom更新为vnode的文本
- 如果新老vnode都有children,表示他们是组件层,则调用updateChildren去做组件层更新
- 如果新vnode是组件层,oldVnode不是,则将当前dom添加新vnode组件的子元素
- 如果oldVnode是组件层,新vnode不是,则操作dom,将oldVnode包含的子元素删除
- 如果新vnode是组件层,oldVnode是文本节点,则将dom的文本清空
在patchVnode部分又浮现了一个新的函数:updateChildren,是在新老vnode都不是文本节点时调用的,这里就是vue的渲染机制的核心
updateChildren
updateChildren中将新老vnode的children进行的循环处理,每一次循环去判断是否有相同的vnode,如果没有则查找当前新vnode的子节点的key是否存在oldVnode的children中,如果不存在在这存在但已经不相同则创建新的dom,否则,如果是新老节点相同,回调patchVnode函数去处理2个节点。 这样进行了递归处理,组件层的更新就完成了。
结尾
本文为看源码分析vue更新机制部分,省略了特殊场景的源码分析,比如ssr、静态组件等。
总结
以上所述是小编给大家介绍的Vue使用虚拟dom进行渲染view的方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 中国武警男声合唱团《辉煌之声1天路》[DTS-WAV分轨]
- 紫薇《旧曲新韵》[320K/MP3][175.29MB]
- 紫薇《旧曲新韵》[FLAC/分轨][550.18MB]
- 周深《反深代词》[先听版][320K/MP3][72.71MB]
- 李佳薇.2024-会发光的【黑籁音乐】【FLAC分轨】
- 后弦.2012-很有爱【天浩盛世】【WAV+CUE】
- 林俊吉.2012-将你惜命命【美华】【WAV+CUE】
- 晓雅《分享》DTS-WAV
- 黑鸭子2008-飞歌[首版][WAV+CUE]
- 黄乙玲1989-水泼落地难收回[日本天龙版][WAV+CUE]
- 周深《反深代词》[先听版][FLAC/分轨][310.97MB]
- 姜育恒1984《什么时候·串起又散落》台湾复刻版[WAV+CUE][1G]
- 那英《如今》引进版[WAV+CUE][1G]
- 蔡幸娟.1991-真的让我爱你吗【飞碟】【WAV+CUE】
- 群星.2024-好团圆电视剧原声带【TME】【FLAC分轨】