cube-ui / question-answer

Q&A for cube-ui
16 stars 7 forks source link

scroll组件,在使用keep-alive的页面里,无法用scrollto方法保存上次浏览的位置 #17

Open GOGOGOSIR opened 5 years ago

GOGOGOSIR commented 5 years ago

我在进入子页面之前会保存当前页面的startY,然后从子页面里面退回来是,在利用scrollto重新定位至上次的位置,在多次操作后,会出现突然返回最开始的位置, 这是线上的链接: (移动端) http://m.harohouse.com/#/

tank0317 commented 5 years ago

你的 demo 我看了。

原因

你使用了懒加载插件 vue-lazyload 。当图片加载完成后插件会修改 img 的 attribute 比如:lazy = 'loaded',这时会触发 Scroll 底层重新计算可滚动距离(底层 better-scroll 使用了 mutationOberser 监听了滚动内容 attribute 修改后会自动重新计算)。正常情况下,这没有问题。

关键是如果网络慢,图片还没有加载完成,你跳到了其他路由,此时图片加载完成后触发重新计算,得到可滚动距离为0。

为什么依然会触发重新计算,为什么是 0?因为你使用了 keep-alive ,跳转后上一个路由对应的 DOM 树是保存在内存里的,未加载完成的图片依然会加载,当图片加载完成后,依然会触发 mutationObserver 去重新计算。此时 Scroll 内容对应的 DOM 并不在文档流里,因此没有高度。最终计算得到的可滚动距离为0。之后任何响应滚动的时候,都只能滚动到顶部。

如何解决呢?

你可以禁用这种情况下的 Scroll 自动重新计算,在 better-scroll 配置项 options 中传递 observeDOM 为 false,默认为 true。

注意:如果你图片加载前的默认图片高度和加载后的真实图片高度不一致,你应该在图片加载完成后手动调用 refresh() 方法重新计算可滚动距离。否则 Scroll 组件并不知道你的内容高度更新了,造成可滚动距离出现异常。

其他

针对你的例子,当上述问题解决后,你是不需要保存跳转前的滚动位置,不需要跳转回来后,手动调用 scrollTo() 滚动到原来的位置的。