Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mpvue重要更新,页面更新机制进行全面升级 #2

Open
sexdevil opened this issue Nov 20, 2018 · 1 comment

Comments

@sexdevil
Copy link

commented Nov 20, 2018

一、原有mpvue更新机制的不足和影响

mpvue实现原理是基于Vue2.js,重写platform部分代码来实现在小程序环境下用Vue组件系统进行运行。在Vue的H5实现中,当我们组件树上的一个组件属性更改后,会触发整个树的检查更新,然后在新老dom树对比算出最小改动后,同步到浏览器的真实dom,这个过程熟悉Vue的开发者很熟悉了,就是diff更新。

但是H5版的diff最后的浏览器runtime代码是基于增删dom节点API进行的,小程序又不提供增删节点的功能,所以为了能在小程序环境实现更新,原版mpvue对整个触发更新检查的V-dom树都取值转换成了小程序对应的JSON,通过setData()接口同步到视图。这个过程在实际运行会造成setData的数据冗余过大。通过代理updateDataToMP打日志的方式我们发现,v-dom树上任意节点的任意属性更改,会引发整棵树的更新,一次形如this.a = 1的操作会引起O(N^2)量级的更新。真实在项目中监控到,一个10个组件左右构成的页面,每次进行一次this.a=1数据更新,在$nextTick渲染时真实传到小程序的数据大概在10k-20k。安卓真机上会造成大概200-300ms的渲染演示,肉眼能较明显觉察。

二、新mpvue更新机制原理和效果

新版Mpvue在每次数据更新的时候,会在Vue监听set方法,每次触发属性更新的时候把当前更新的属性key放在当前V-dom的__keyPath属性中。一次更新全部触发后,在实际render过程中遍历keyPath属性,只选择更新的属性放到json里,调用Page.setData来进行更新操作。同时在Vue.$nextTick函数里,触发完所有的render更新后会清理掉全部keyPath,防止下次再更新又冗余。通过这种操作,this.a=1可以O(N^2)量级降低到O(1).上面例子中每次更新10k-20k的页面,在业务中有比如用户操作引起某个组件数字+1,关闭弹窗等操作时,更新量降低到几个字节。安卓卡顿的问题也从框架角度完美解决

三、新的监测机制

由于Vue实现机制,对于v-if显示/删除节点,v-dom是会进行删除操作,无法跟踪检查,所以目前还是会触发v-if的节点及其子节点从v-if=false 变成v-if=true时无法减少更新量。为了开发者们更好的评估自己页面的性能找到优化点,新版Mpvue添加了Vue.config._mpTrace属性,把这个属性置true的情况下可以看到console里会打印每500ms更新的数据量,帮助你结合真机表现彻底解决卡顿等性能问题。

注意,监控方法依然是通过JSON.stringfy(data)实现,线上代码不要出现否则会有额外性能损失

@sexdevil sexdevil changed the title # **mpvue重要更新,页面更新机制进行全面升级** mpvue重要更新,页面更新机制进行全面升级 Nov 20, 2018

@limichange

This comment has been minimized.

Copy link

commented Nov 21, 2018

😂其实大家更关心数据不清除和页面周期混乱的问题

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.