也就是说使用keep-alive的组件不会触发destroyed钩子方法,这就是取消监听失败的原因。根据文档介绍,keep-alive切换时,会触发自己的activeted和deactiveted两个钩子函数,可以理解为vue的created和destroyed两个钩子,因此需要修改代码,在deactivated时候取消监听,同时在activated的时候恢复监听,否则切回去的时候滚动监听也不会有效果:
//keep-alive钩子函数,组件恢复时触发 activated(){ window.addEventListener('scroll', this.isScrollBot)}, //keep-alive钩子函数,组件变为不可用时触发 deactivated(){ window.removeEventListener('scroll', this.isScrollBot)}
修改后的效果完全符合预期,切换路由页面保留当位置,不会重复请求接口而且也不会在专辑列表组件外部触发滚动加载。
二、关于keep-alive
既然用到了keep-alive,就通过文档简单总结下相关使用:
上面已经说过,通过keep-alive包裹的组件,在不活动时会缓存组件实例,不会对组件进行销毁,再次处于活动状态时,会读取缓存的内容并保存组件状态,不用重复请求接口获取数据。
(1)最基本使用基本用法:
基本用法: <keep-alive> <component :is="view"></component> </keep-alive> 也可以根据条件判断: <keep-alive> <comp-a v-if="a > 1"></comp-a> <comp-b v-else></comp-b> </keep-alive> 这个时候触发两个组件切换时,组件内的数据和状态都会得到保存,如果有input输入框,输入框内容会保留
(2)有条件的缓存
keep-alive提供了include、exclude、max三个参数,前两个允许组件有条件的进行缓存,两者都可以接受字符串、正则、数组形式;max表示最多可以缓存多少个组件,接受一个number类型。
<keep-alive include="a,b"> <component :is="view"></component> </keep-alive> 此时只有a、b两个组件会触发keep-alive,此处的名字是组件内部name对应名字,如果name不存在,会查找父组件里components里注册的名字,如果也不存在则不会匹配。 正则和数组方法同上,但是需要用v-bind:include=''方式。 <keep-alive :max="10"> <component :is="view"></component> </keep-alive>
(3)钩子函数
两个钩子函数activated和deactivated,上面已经说过,分别在组件恢复活动状态和组件失去活动状态时触发,可以起到类似created和destroyed钩子作用。
以上是对keep-alive的个人使用和理解,如有不足还望指正~
总结