Vue的keep-alive|Vue的keep-alive 实现滑动定位缓存
Situation
首先该项目是一个h5项目,有一个滑动列表页,当我滑动点击列表项,会进入到详情页,当我退出的时候,我希望还能定位到我刚刚点进来的位置。
【Vue的keep-alive|Vue的keep-alive 实现滑动定位缓存】Task
我们的目的是定位滑动位置。在返回的时候应该回到刚刚的滑动位置。
所以我们有两个关键点,第一个是怎么定位滑动位置,第二是返回的时候怎么回到滑动位置。滑动位置的话我们可以获取到滑动容器的scrollTop值,然后返回的时候设置滑动容器的scrollTop就可以定位。
Action
1. 采用scrollBehavior 函数
使用前端路由,当切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置,就像重新加载页面那样。 vue-router 能做到,而且更好,它让你可以自定义路由切换时页面如何滚动。
const router = new VueRouter({
routes: [...],
scrollBehavior (to, from, savedPosition) {
// return 期望滚动到哪个的位置
}
})
scrollBehavior 方法接收 to 和 from 路由对象。第三个参数 savedPosition 当且仅当 popstate 导航 (通过浏览器的 前进/后退 按钮触发) 时才可用。
所以在定义router的地方,挂载了scrollBehavior函数。
- 问题:savedPosition打印出来的x,y坐标,不是想要的,不准确。
- 分析:因为scrollBehavior是挂载在路由身上,它对应的应该是一个整个路由组件,而我的滑动区域是组件里面的一个固定区域,也就是说,我应该把scrollTop挂在滑动区域,但是整个页面结构不允许我这样做。所以尝试第二种方法,keep-alive
Keep-alive 是什么?这可不是http保持长链接的keep-alive哦但是有个问题是,它不会缓存我们的滑动位置,我们需要手动记录位置。
keepalive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染 。也就是所谓的组件缓存
a. 在滑动的时候记录滑动组件的scrollTop (这里可以加一个节流函数)
onScroll(e: Event) {
const { scrollTop } = e.target as HTMLElement;
this.scrollTop = scrollTop;
// 记录滑动位置,回来时恢复到此位置
}
keep-alive的声明周期执行b. 所以我们在activated声明周期中定位我们的位置
- 页面第一次进入,钩子的触发顺序:
created-> mounted-> activated,
退出时触发 deactivated 当再次进入(前进或者后退)时,只触发 activated- 事件挂载的方法等,只执行一次的放在 mounted 中;组件每次进去执行的方法放在 activated 中;
activated() {
// 恢复之前保存的位置
(this.$refs.scroller as HTMLElement).scrollTop = this.scrollTop;
}
Result
被keepalive包含的组件不会被再次初始化,也就意味着不会重走生命周期函数。但是我们可以通过
activated, deactivated 两个生命周期进行控制。而且也避免了重新加载数据。
思考:
因为之前的技术栈是react,所以每次我写vue的时候都会下意识思考如果是用react我会怎么去实现。
- 在 React 中,我们通常会使用路由去管理不同的页面,而在切换页面时,路由将会卸载掉未匹配的页面组件,所以上述列表页例子中,当用户从详情页退回列表页时,会回到列表页顶部,因为列表页组件被路由卸载后重建了,状态被丢失。
- 如果说按照之前的做法,我可能是onScroll事件监听滑动,或者是点击列表项的时候获取到容器的scrollTop,然后把scrollTop存到我们model里面,并且需要判断路由状态,如果是从详情页跳转的,则需要读取scrollTop,在componentDidMount中定位,如果是从其他页面,比如首页进入到列表页,就不需要重新定位
推荐阅读
- 热闹中的孤独
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 放屁有这三个特征的,请注意啦!这说明你的身体毒素太多
- 一个人的旅行,三亚
- 布丽吉特,人生绝对的赢家
- 慢慢的美丽
- 尽力
- 一个小故事,我的思考。
- 家乡的那条小河
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量