-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
在渲染时使用新的diff算法来减少Vue组件更新引起的Page.setData的实际更新量,达到提升页面性能的目的 #1165
Conversation
1、core/observer的set方法中,监听对象更新值时,用__keyPath:{key:true}方式把更新的key值绑定在vm数据对象上 2、每次真实调用setData前,用mp/runtime/diffData.js进行检查优化大小,规则有 A.第一次vm渲染到小程序上,全量更新,并记下标志 B.第二次及以后再更新,检查_data对象,如果有__keyPath,跟据__keyPath更新,没有 __keyPath表示没有更新,不放到Page.setData B1._data遇到Object类型,检查Object类型__keyPath,存在的话深度遍历所有属性 递归检查更新,不存在__keyPath可能是this.obj = {}重新写对象值造成set没捕捉到, 使用脏检查和页面数据对比更新 B2._data遇到Array类型,直接脏检查,避免数组不能记录__keyPath造成丢失 B3._props属性由于父组件传入不走set,所以遍历_props,值类型直接更新,对象类型 深度遍历进入步骤B1,数组进入B2 B4.遍历上述后最终更新数据再加入_computedWatchers,_mpProps B5.组件树上的节点都完成更新后调用Vue.nextTick钩子,清理所有对象上的__keyPath 为下次检查更新做准备 C.diff优化好data后,如果在Vue.config.devtool == true时打印500ms内的更新量 方便使用者检查页面的更新情况 D.diff好的JSON中,删掉原来的$root.0={},只把必要的更新给Page.setData使用 3、使用效果:减少了只改动一个根节点属性却造成整个组件树的数据都传递给 Page.setData的情况,从而减少因为setData量大引起的真机尤其安卓卡顿的情况
希望尽快验证合并 如果mpvue项目组没有太多能力拓展新功能 希望有时间审核一下PR 如果都没有 .... |
急需这个~~ |
非常给力 |
使用报错。。。。 |
报错,麻烦看下什么情况 |
发下引发错误的mpvue页面源码吧 |
Setting data field "$root.0,6.text" to undefined is invalid. this.text = undefined会引发小程序错误,框架已更新,对于这种情况不更新视图 |
jsEnginScriptError Converting circular structure to JSON TypeError: Converting circular structure to JSON 这种情况判定是由于this.a= undefined引发,最新commit已兼容处理 |
依然没有解决,应该是使用Vuex 有问题
|
VM18845:1 jsEnginScriptError |
Converting circular structure to JSON我这里已fix提交,感谢反馈 |
这个已经合并了么???什么时候可以拉到最新代码呢? |
尝试了一下,picker 组件还是存在拖动后瞬间回到顶部的问题,是我用的方式不对么, 和#639 解决的是同一个问题么 |
|
怎么更新的?arr.push(1)?
----- 原始邮件 -----
发件人:825553819 <notifications@github.com>
收件人:Meituan-Dianping/mpvue <mpvue@noreply.github.com>
抄送人:toukang <super00778@sina.com>, Author <author@noreply.github.com>
主题:Re:_[Meituan-Dianping/mpvue]_在渲染时使用新的diff算法来减少Vue组件更新引起的Page.setData的实际更新量,达到提升页面性能的目的_(#1165)
日期:2018年12月01日 17点02分
1、core/observer的set方法中,监听对象更新值时,用__keyPath:{key:true}方式把更新的key值绑定在vm数据对象上
2、每次真实调用setData前,用mp/runtime/diffData.js进行检查优化大小,规则有
A.第一次vm渲染到小程序上,全量更新,并记下标志
B.第二次及以后再更新,检查_data对象,如果有__keyPath,跟据__keyPath更新,没有
…__keyPath表示没有更新,不放到Page.setData
B1._data遇到Object类型,检查Object类型__keyPath,存在的话深度遍历所有属性
递归检查更新,不存在__keyPath可能是this.obj = {}重新写对象值造成set没捕捉到,
使用脏检查和页面数据对比更新
B2._data遇到Array类型,直接脏检查,避免数组不能记录__keyPath造成丢失
B3._props属性由于父组件传入不走set,所以遍历_props,值类型直接更新,对象类型
深度遍历进入步骤B1,数组进入B2
B4.遍历上述后最终更新数据再加入_computedWatchers,_mpProps
B5.组件树上的节点都完成更新后调用Vue.nextTick钩子,清理所有对象上的__keyPath
为下次检查更新做准备
C.diff优化好data后,如果在Vue.config.devtool == true时打印500ms内的更新量
方便使用者检查页面的更新情况
D.diff好的JSON中,删掉原来的$root.0={},只把必要的更新给Page.setData使用
3、使用效果:减少了只改动一个根节点属性却造成整个组件树的数据都传递给
Page.setData的情况,从而减少因为setData量大引起的真机尤其安卓卡顿的情况
What kind of change does this PR introduce? (check at least one)
Bugfix
Feature
Code style update
Refactor
Build-related changes
Other, please describe:
Does this PR introduce a breaking change? (check one)
Yes
No
If yes, please describe the impact and migration path for existing applications:
The PR fulfills these requirements:
It's submitted to the dev branch for v2.x (or to a previous version branch), not the master branch
When resolving a specific issue, it's referenced in the PR's title (e.g. fix #xxx[,#xxx], where "xxx" is the issue number)
All tests are passing
New/updated tests are included
If adding a new feature, the PR's description includes:
A convincing reason for adding this feature (to avoid wasting your time, it's best to open a suggestion issue first and wait for approval before working on it)
Other information:
我拉取完最新代码之后,试了一下发现一个新问题。 比如, 在data里面初始化一个数据 如arr=[1,2,3],
页面渲染这个数组。 通过事件更新数组或者加入新的元素,页面数据不会更新。调试mpvue源码之后发现传入的page.setData 的数据没有出现修改的那个数组。最后在compareAndSetDeepData 方法里面发现 更新数据是通过代码 oldData === null || JSON.stringify(oldData) !== JSON.stringify(newData) 来判断。如果数据是引用类型 那么在我更新完数据之后 vm.$root.$mp.page.data 里面的数据也会改变 ,那么在检查是否需要setData的时候 oldData 和newData 就会永远相同, 因此新修改的数据就会不符合更新的要求。 这些仅是我个人分析所得,也不知道说的是否正确,希望mpvue的作者能试一下我说的情况。
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or mute the thread.
|
下面是我的测试代码 {{item}} <input type="button" value="add1" @click="add"/> <input type="button" value="update2" @click="update"/> mpvue 引入是develope 分支中的 packages/mpvue/index.js |
代码没有贴全 在来一次
|
感谢反馈~之前
感谢反馈~之前测试用例没有写直接操作this上的数组变量�,问题定位很专业 👍 ,个人分支已更新成数组强制更新视图了,https://github.com/sexdevil/mpvue ,测试OK后我们会合并dev分支 |
按照您的修改我更新的代码,上面操作数组数据的问题解决了。个人感觉如果数组强制更新,不知道会不会带来较多额外的性能消耗。测试发现修改其他定义的变量(跟上面的arr是平级变量,比如 name: ‘aa’, 将name改成其他值)数组arr也会被传入到setDate方法里面。如果页面中arr中的数据结构复杂且数据较多或者页面中有多个数组的变量,不需要更新时也传入到setDate方法里面,性能上不知道会怎样,尤其是在页面滚动事件中修改变量的情况。 |
这个得后续再找其他方法优化了 目前就是数组这里和之前版本一样性能。影响的大头还是组件树整体更新的问题,这次feature先解决这个 |
TypeError: Cannot read property 'dep' of undefined 为什么会报这种错误 |
请贴上复现的代码 |
Setting data field "$root.0,1-4.studioId" to undefined is invalid. 某个计算属性的值是undefined时,就会提示这个错误,代码如下便可复现: computed: {
studioId () {
return undefined // 某个表达式被计算出来undefined
}
} |
复现的Vue文件和数据发一下
----- 原始邮件 -----
发件人:lishenghan <notifications@github.com>
收件人:Meituan-Dianping/mpvue <mpvue@noreply.github.com>
抄送人:toukang <super00778@sina.com>, Author <author@noreply.github.com>
主题:Re:_[Meituan-Dianping/mpvue]_在渲染时使用新的diff算法来减少Vue组件更新引起的Page.setData的实际更新量,达到提升页面性能的目的_(#1165)
日期:2018年12月26日 15点20分
请问这个问题解决了吗,在组件里面传入prop就会有这个问题
VM1334:1 jsEnginScriptError Converting circular structure to JSON TypeError: Converting circular structure to JSON at JSON.stringify (<anonymous>) at Object.e [as publish] (http://127.0.0.1:13778/appservice/appservice?t=1545807713399:4211:18891) at Object.publish (http://127.0.0.1:13778/appservice/__dev__/WAService.js:1:117468) at ce (http://127.0.0.1:13778/appservice/__dev__/WAService.js:1:252387) at Object.$t [as invokeWebviewMethod] (http://127.0.0.1:13778/appservice/__dev__/WAService.js:1:302744) at Function.value (http://127.0.0.1:13778/appservice/__dev__/WAService.js:1:686429) at s.value (http://127.0.0.1:13778/appservice/__dev__/WAService.js:1:689972) at http://127.0.0.1:13778/appservice/common/vendor.js:6510:3 at http://127.0.0.1:13778/appservice/common/vendor.js:6498:21 at VueComponent.updateDataToMP [as $updateDataToMP] (http://127.0.0.1:13778/appservice/common/vendor.js:6535:3) console.error @ VM1334:1 errorReport @ WAService.js:1 (anonymous) @ WAService.js:1 O @ WAService.js:1 value @ WAService.js:1 (anonymous) @ index.js:5617 (anonymous) @ index.js:5605 updateDataToMP @ index.js:5642 patch @ index.js:4959 Vue._update @ index.js:2080 updateComponent @ index.js:2188 get @ index.js:2518 Watcher @ index.js:2507 mountComponent @ index.js:2192 (anonymous) @ index.js:5804 initMP @ index.js:5137 global.webpackJsonpMpvue.Vue$3.$mount @ index.js:5803 init @ index.js:3055 createComponent @ index.js:4471 createElm @ index.js:4432 createChildren @ index.js:4542 createElm @ index.js:4447 updateChildren @ index.js:4694 patchVnode @ index.js:4769 patch @ index.js:4883 patch @ index.js:4958 Vue._update @ index.js:2090 updateComponent @ index.js:2188 get @ index.js:2518 run @ index.js:2595 flushSchedulerQueue @ index.js:2363 (anonymous) @ index.js:609 nextTickHandler @ index.js:556 Promise resolved (async) timerFunc @ index.js:571 queueNextTick @ index.js:619 queueWatcher @ index.js:2450 update @ index.js:2585 notify @ index.js:686 reactiveSetter @ index.js:914 proxySetter @ index.js:2710 (anonymous) @ course-directory.ts:59 step @ main.js:217 (anonymous) @ main.js:183 fulfilled @ main.js:150 run @ es6.promise.js:73 (anonymous) @ es6.promise.js:90 flush @ _microtask.js:16 global.webpackJsonpMpvue.module.exports @ _invoke.js:3 queue.(anonymous function) @ _task.js:33 run @ _task.js:19 (anonymous) @ _ctx.js:8 (anonymous) @ WAService.js:1 (anonymous) @ WAService.js:1 setTimeout (async) setTimeout @ WAService.js:1 defer @ _task.js:75 setImmediate @ _task.js:35 notify @ _microtask.js:55 (anonymous) @ _microtask.js:64 notify @ es6.promise.js:54 $resolve @ es6.promise.js:160 (anonymous) @ _ctx.js:8 options.success @ api.ts:236 function.e.(anonymous function) @ WAService.js:1 (anonymous) @ WAService.js:1 _e @ WAService.js:1 (anonymous) @ WAService.js:1 ht.emit @ WAService.js:1 di @ WAService.js:1 (anonymous) @ WAService.js:1 (anonymous) @ WAService.js:1 e @ appservice?t=1545807713399:4211 (anonymous) @ appservice?t=1545807713399:4211 t.emit @ appservice?t=1545807713399:4211 callback @ appservice?t=1545807713399:4211 setTimeout @ appservice?t=1545807713399:4211 (anonymous) @ WAService.js:1 (anonymous) @ WAService.js:1 setTimeout (async) setTimeout @ WAService.js:1 d @ appservice?t=1545807713399:4211 o @ appservice?t=1545807713399:4211 y.onreadystatechange @ appservice?t=1545807713399:4211 XMLHttpRequest.send (async) h @ appservice?t=1545807713399:4211 createRequestTask @ appservice?t=1545807713399:4211 invoke @ appservice?t=1545807713399:4211 invoke @ WAService.js:1 Q @ WAService.js:1 ie @ WAService.js:1 (anonymous) @ WAService.js:1 li @ WAService.js:1 i @ WAService.js:1 t @ WAService.js:1 (anonymous) @ WAService.js:1 (anonymous) @ WAService.js:1 (anonymous) @ WAService.js:1 (anonymous) @ WAService.js:1 (anonymous) @ WAService.js:1 (anonymous) @ api.ts:248 Promise @ es6.promise.js:175 (anonymous) @ api.ts:173 step @ api.ts:41 (anonymous) @ api.ts:22 (anonymous) @ api.ts:16 Promise @ es6.promise.js:175 global.webpackJsonpMpvue.__awaiter @ api.ts:12 global.webpackJsonpMpvue.ApiBase.doRequest @ api.ts:160 global.webpackJsonpMpvue.ApiBase.doGet @ api.ts:255 (anonymous) @ course.service.ts:140 step @ course.service.ts:39 (anonymous) @ course.service.ts:22 (anonymous) @ course.service.ts:15 Promise @ es6.promise.js:175 global.webpackJsonpMpvue.__awaiter @ course.service.ts:1 global.webpackJsonpMpvue.CourseService.getDirectory @ course.service.ts:131 (anonymous) @ course-directory.ts:57 step @ main.js:217 (anonymous) @ main.js:183 (anonymous) @ main.js:167 Promise @ es6.promise.js:175 global.webpackJsonpMpvue.272.__awaiter @ main.js:147 global.webpackJsonpMpvue.272.CourseDirectory.onGetChapterList @ course-directory.ts:55 boundFn @ index.js:191 global.webpackJsonpMpvue.272.CourseDirectory.onLoad @ course-directory.ts:49 callHook$1 @ index.js:4974 onLoad @ index.js:5256 (anonymous) @ WAService.js:1 __callPageLifeTime__ @ WAService.js:1 jt @ WAService.js:1 Vt @ WAService.js:1 (anonymous) @ WAService.js:1 (anonymous) @ WAService.js:1 ht.emit @ WAService.js:1 emit @ WAService.js:1 (anonymous) @ WAService.js:1 (anonymous) @ WAService.js:1 e @ appservice?t=1545807713399:4211 n.registerCallback.t @ appservice?t=1545807713399:4211 l.forEach.t @ appservice?t=1545807713399:4211 (anonymous) @ appservice?t=1545807713399:4211 s.onmessage @ appservice?t=1545807713399:4211 VM1334:1 jsEnginScriptError Converting circular structure to JSON TypeError: Converting circular structure to JSON at JSON.stringify (<anonymous>) at Object.e [as publish] (http://127.0.0.1:13778/appservice/appservice?t=1545807713399:4211:18891) at Object.publish (http://127.0.0.1:13778/appservice/__dev__/WAService.js:1:117468) at ce (http://127.0.0.1:13778/appservice/__dev__/WAService.js:1:252387) at Object.$t [as invokeWebviewMethod] (http://127.0.0.1:13778/appservice/__dev__/WAService.js:1:302744) at Function.value (http://127.0.0.1:13778/appservice/__dev__/WAService.js:1:686429) at s.value (http://127.0.0.1:13778/appservice/__dev__/WAService.js:1:689972) at http://127.0.0.1:13778/appservice/common/vendor.js:6510:3 at Function.later (http://127.0.0.1:13778/appservice/common/vendor.js:6481:19) at http://127.0.0.1:13778/appservice/__dev__/WAService.js:1:101815
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or mute the thread.
|
正常,computed现在会被翻译成 this.setData({$root.0,1-4.studioId:undefined}); |
但是之前的mpvue版本没有这个问题啊。 |
diff没有任何改善,前后更新的数据量是一样的 |
What kind of change does this PR introduce? (check at least one)
Does this PR introduce a breaking change? (check one)
If yes, please describe the impact and migration path for existing applications:
The PR fulfills these requirements:
dev
branch for v2.x (or to a previous version branch), not themaster
branchfix #xxx[,#xxx]
, where "xxx" is the issue number)If adding a new feature, the PR's description includes:
Other information: