vue keep-alive组件使用探究

vue keep-alive组件使用探究

最近在使用vue的keep-alive组件实现页面缓存的时候遇到了一些问题
最主要的困惑是没有分清meta标签中的keeAlive的true和false值的影响,以为能控制keep-alive组件是否缓存页面,后面发现我想错了。

keep-alive只是一个组件,用来缓存页面,它本事是很机械的。

  1. 不管使用这种
<keep-alive>
    <router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
    <router-view v-if="!$route.meta.keepAlive"></router-view>

2.还是这种

<keep-alive include="c">
	  <router-view></router-view>
</keep-alive>

本质上是一样的,直接在开始的时候定义好了哪些页面需要被缓存。这就会出现一个问题,当一个页面需要动态判断是否需要被缓存时就会无法实现。
比如,从A入口页面到B列表页需要刷新页面,从B滚动浏览了某个tab分类下的商品点击进入C详情页希望被缓存。这就需要B页面被缓存,这时候B页面的缓存时需要根据路由场景动态判断的。这一点是includev-if="$route.meta.keepAlive"无法实现的。

解决方案

  1. 通过在B列表页判断页面来源,使用actived和created判断进入页面的来源和次数,进而确定是否要调用函数重载页面。实现思路是一定缓存B页面,但是在A页面进入时调用函数发送ajax更新数据和视图。
created() {
		// console.log('proall','--created')
		this.isFirst = false
		this.showTopBar(true)
    },
activated () {
	// console.log('activated')
	const prevpage = this.$store.state.prevpage
	// 从首页二次进来需要重载
	if (prevpage === 'baopro' && this.isFirst) {
		this.reload()
	// 其他页面返回,无需重载,返回锚点
	} else { 
	 // 这里时回滚记录的页面高度,因为scrollBehavior钩子无效才使用该方式
		document.getElementById('baopro').scrollTop = this.$store.state.topDistance
	}
 }

2.通过在B列表页判断页面去向,使用beforeRouteLeave钩子返回A页面的时候,就把所有的页面缓存清掉。实现思路是一定缓存B页面,但是返回A页面的时候清除缓存,这样A重新进入B就会重载。

beforeRouteLeave(to,from,next) {
	if (to.name === 'a') {
	  this.$vnode.parent.componentInstance.cache = {}
	  this.$vnode.parent.componentInstance.keys = []
	}
	next()
}

我更倾向于第二种实现,因为更简洁,附上代码。

  • router.js
  {
	path: '/a',
		name: 'a',
		component: a,
		props: true,
		meta: {
			keepAlive: false
		}
	},{
		path: '/b',
		name: 'b',
		component: b,
		props: true,
		meta: {
			keepAlive: true
		}
	},
	{
		path: '/c',
		name: 'c',
		component: c,
		props: true,
		meta: {
			keepAlive: false
		}
	}
  • App.vue
<template>
  <div id="app">
    <keep-alive>
      <router-view v-if="$route.meta.keepAlive"></router-view>
    </keep-alive>
    <router-view v-if="!$route.meta.keepAlive"></router-view>
    // 这里是方式一用来查看meta的keepAlive属性的值的
	<div>{{String($route.meta.keepAlive)}}</div>
  </div>
</template>
  • a.vue
<template>
	<div class="fa">
		<button @click="$router.push('b')">B</button>
	</div>
</template>
<style lang="scss" scoped>
	button {
		width: 50px;
		height: 30px;
		margin-top: 40px;
		margin-right: 40px;
	}
</style>
  • b.vue
<template>
	<div class="fa">
		<div class="inner" :style="{background:item.bg}" v-for="item in list" :key="item.id" @click="go(item)">
		</div>
		<button @click="$router.back()">A</button>
		<button @click="$router.push('c')">C</button>
	</div>
</template>

<script>
	export default {
		name:'B',
		data () {
			return {
				list:[
					{bg:'yellow',id:0},
					{bg:'yellow',id:1},
					{bg:'yellow',id:2},
				]
			}
		},
		beforeRouteLeave(to,from,next) {
			if (to.name === 'a') {
			  this.$vnode.parent.componentInstance.cache = {}
			  this.$vnode.parent.componentInstance.keys = []
			}
			next()
		},
		methods: {
			go(item) {
				item.bg =  item.bg === 'red' ? 'yellow' : 'red'
			}
		}
	}
</script>

<style lang="scss" scoped>
	.inner {
		width: 100%;
		height: 100px;
		margin-top: 50px;
		/* background-color: yellow; */
	}
	.inner > span {
			font-size: 30px;
		}
	button {
		width: 50px;
		height: 30px;
		margin-top: 40px;
		margin-right: 40px;
	}
</style>

  • c.vue
<template>
	<div class="fa" >
		<p>这是页面C</p>
		<button @click="$router.back()">点击返回B</button>
	</div>
</template>
<style lang="scss" scoped>
	.fa {
		font-size: 40px;
	}
</style>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值