0
点赞
收藏
分享

微信扫一扫

你真的了解keep-alive吗?


了解之前你先从动态组件说起~

component

有的时候,在不同组件之间进行动态切换是非常有用的,比如在一个多标签的界面里:

你真的了解keep-alive吗?_表单


上述内容可以通过 Vue 的 ​​<component>​​ 元素加一个特殊的 is attribute 来实现:

<template>
<div class="hello">
<button @click="handleAbout">About</button>
<button @click="handleHome">Home</button>
<keep-alive>
<component :is="currentTab"></component>
</keep-alive>
</div>
</template>

<script>
import About from "./about";
import Home from "./home";
export default {
name: "HelloWorld",
components: {
About,
Home
},
props: {
msg: String
},
data() {
return {
currentTab: 'About'
};
},
methods: {
handleAbout () {
this.currentTab = 'About'
},
handleHome () {
this.currentTab = 'Home'
}
}
};
</script>

component默认每次都会销毁和重建,那么为了性能优化,我们可以使用keep-alive缓存,缓存还有一些其他的作用,比如切换时保留滚动位置,切换时保留页面输入的内容,等等等

keep-alive

将keep-alive包裹你的component

<keep-alive>
<component :is="currentTab"></component>
</keep-alive>

这样就可以保留tab之间用户的输入的信息了,但是并不能保留滚动的位置,不信你看下面代码,一个tab里面不需要滚动,而另外一个tab需要滚动。

about.vue

<template>
<div>
about
</div>
</template>

<script>
export default {

}
</script>

<style lang="">

</style>

home.vue

<template>
<div class="wrapper">
<ul>
<li v-for="(item, index) in 50" :key="index">
{{item}}
</li>
</ul>
</div>
</template>

<script>
export default {

}
</script>

<style>
.wrapper {
height: 200px;
overflow: auto;
}
</style>

写法上没啥问题,但就是每次切换的时候不能保留滚动位置,怎么办???

记录滚动位置

解决办法

不使用component和keep-alive组件,使用v-show代替

<home v-show="currentTab==='Home'"></home>
<about v-show="currentTab==='About'"></about>

这里有个需要注意的地方就是,需要把滚动设置到组件里面去,而不是他们共同的父元素,因为他们不能共用滚动,共用滚动的话滚动位置又乱了,所以不要为了偷懒而设置在在父元素中,比如下面代码:

<div class="container">
<home v-show="currentTab==='Home'"></home>
<about v-show="currentTab==='About'"></about>
</div>

.container {
height: 200px;
overflow: auto;
}

其实很多人认为keep-alive能保留滚动位置,也许是你在配合vue-router的时候这样使用过,看下面代码

<keep-alive>
<router-view></router-view>
</keep-alive>

其实keep-alive只能通过点击浏览器自带的返回按钮才能记录位置,如果你需要在A切换到B再切换到A,通过JS的路由跳转是不能记录位置的。来个图片吧,这样直观一点:

你真的了解keep-alive吗?_正则表达式_02

通常我们有这样的需求,商品列表跳转的商品详情页,然后返回到商品列表,这个时候是要保留滚动位置的,既然Keep-alive做不到,我们可以使用其他方法。

通过在页面中记录滚动位置,当组件再次被激活时,重新设置一下页面的滚动,代码如下:

export default {
// 1.绑定滚动事件
mounted () {
window.addEventListener('scroll', this.handleScroll)
},

// 3.当再次进入(前进或者后退)时,只触发activated(注:只有在keep-alive加载时调用)
activated () {
if (this.scroll > 0) {
this.$nextTick(() => {
document.documentElement.scrollTop = this.scroll
window.addEventListener('scroll', this.handleScroll)
})
}
},

// 4.deactivated 页面退出时关闭事件 防止其他页面出现问题
deactivated () {
window.removeEventListener('scroll', this.handleScroll)
},

methods: {
// 2.滚动时候保留位置
handleScroll () {
this.scroll = document.documentElement.scrollTop
}
}
};
</script>

有时候我们的页面需要keep-alive保留状态,有些时候我们的页面不需要keep-alive保留状态,这个时候可以使用属性include和exclude属性处理。

include 和 exclude 属性允许组件有条件地缓存。二者都可以用逗号分隔字符串、正则表达式或一个数组来表示:

<keep-alive :include="['a', 'b']">
<component :is="view"></component>
</keep-alive>

更多内容请参考官方文档:​​链接​​

总结

  1. keep-alive可以保留页面的状态,比如表单输入
  2. keep-alive可以保留触发返回键的滚动位置
  3. keep-alive不能保留动态组件的滚动位置,需要使用v-show代替
  4. keep-alive不能保留通过路由切换页面时候的滚动位置,需要在页面组件中单独处理
  5. keep-alive可以通过exclude排除不需要保留状态的页面
  6. 使用了keep-alive才会触发的生命周期是activated 和 deactivated


举报

相关推荐

0 条评论