keep-alive 缓存

缓存的场景各种各样,稍微一改代码就大不相同。
所以我写的只是这一种场景:缓存一个页面(只是一个页面!),并且记录下这个页面的滚动位置。

必要的因素:

1.因为设置滚动是在router.js里scrollBehavior:设置的是 body滚动距离,所以这个页面不能有其他可以滚动的标签。

2.像mint-ui的上拉加载组件是父节点必须有overflow:hidden.所以也不能使用。

3.最好不要有tabbar,或者有的话在下面再加一个相等高度的div。要不然看不到最下面的东西。

用到的功能点:

1.记录滚动距离: window.addEventListener('scroll', this.handleScroll);

2.设置body滚动距离:router.js里scrollBehavior

3.记录缓存组件:app.vue:<keep-alive>

正式开始:
1.在app.vue文件:

  <div id="app">
    <!-- 缓存需要 -->
    <keep-alive :max='1'>      
        <router-view v-if="$route.meta.keepAlive"/>    
    </keep-alive>    
    <router-view v-if="!$route.meta.keepAlive"/>
  </div>

官网有keep-alive详细的解释-->传送门
我这里用到了max解释:max - 数字。最多可以缓存多少组件实例。
就是我上面提到的我只缓存一个实例
而$route.meta.keepAlive在router.js里设置

2.router.js:

  {
          path:'/index3',
          name:'index3',
          meta:{keepAlive:true},
          component:() => import('./views/index3.vue')
        },

3.这个时候就可以缓存页面了。接下来是保存页面滚动距离。
缓存页面它有自己的生命周期:
activated:组件激活时调用
deactivated:组件停用时调用。
每次进缓存页面时都要记录滚动距离,所以在 activated 里调用函数并且滚动距离及时保存在sessionStorage:
index3.vue :

        mounted () {
            window.addEventListener('scroll', this.handleScroll);
        },
        // 缓存组件的话,第二次是不走mounted的,
        activated() {
            window.addEventListener('scroll', this.handleScroll);
        },
 methods: {
             handleScroll () {
                let scrollY = window.scrollY
                sessionStorage.setItem('height',JSON.stringify({h:scrollY}));
                // console.log(scrollY,'scrollYindex333')
             }, 
        
        },

4.因为这个window.scrollY是全局的,所以在这个组件销毁时清除this.handleScroll

 deactivated () {
            window.removeEventListener('scroll', this.handleScroll)
        }

5.记录页面滚动距离成功,这时候再进这个页面就要设置页面的滚动距离了,
在router.js里:

export default new Router({
routes:{
.......
},
   scrollBehavior (to, from, savedPosition) {
      // 从 A ---->  B
      //   from     to
      // console.log(to,'to---------')
      if (to.name === 'index3') {
        // 拿到滚动距离!!!
        let num = JSON.parse(sessionStorage.getItem('height'))
        num = num ? num : 0
        return { x: 0, y: num.h }
      } 
    }

下面是index3的全部代码:

<template>
    <div>
            index3
            <p>------分割线1---------</p>
            <p>------分割线2---------</p>
            <p>------分割线3---------</p>
            <p>------分割线4---------</p>
            <p>------分割线5---------</p>
            <input type="text" style="height:60px;color:red">
            <p>------分割线6---------</p>
            <p>------分割线7---------</p>
            <p>------分割线8---------</p>
            <p>------分割线9---------</p>
            <p>------分割线10---------</p>
            <p>------分割线11---------</p>
            <p>------分割线12---------</p>
            <p>------分割线13---------</p>
            <p>------分割线14---------</p>
            <p>------分割线15---------</p>
            <p>------分割线16---------</p>
            <p>------分割线1---------</p>
            <p>------分割线2---------</p>
            <p>------分割线3---------</p>
            <p>------分割线4---------</p>
            <p>------分割线5---------</p>
    </div>
</template>
<script>
  export default {
        name: 'index3',
        data() {
            return {}
        },
        methods: {
             handleScroll () {
                let scrollY = window.scrollY
                sessionStorage.setItem('height',JSON.stringify({h:scrollY}));
                // console.log(scrollY,'scrollYindex333')
             }, 
        
        },
        // 及时地销毁
        mounted () {
            window.addEventListener('scroll', this.handleScroll);
        },
        destroyed () {
        /* 加上keep-alive 则这个生命周期就不会走了。。。所以把清除放到deactivated */
        },
        // 缓存组件的话,第二次是不走mounted的,
        activated() {
            window.addEventListener('scroll', this.handleScroll);
        },
        deactivated () {
            window.removeEventListener('scroll', this.handleScroll)
        }
    }
</script>
<style>

</style>

经历了一周的缓存组件较劲,以下是我的错误示范。

1>

其实很想动态清除缓存组件,只是现在还没有找到最好的解决方案。网上说的用this.$destroy()这种方法是不可行的,加上之后缓存页面不会再缓存,跟正常页面没有两样。不需要再试了。

2>

网上说的清除缓存使用this.$vnode.
我没有试成功,一周了。。太疲惫了。。。
首先我要缓存的组件是二级路由页面,压根打印不到 this.vnode.parent 是null。所以只能是一级路由页面parent才有值。并且我发现这个parent只有在从缓存组件跳到其他页面时才会有值。有兴趣的可以试试,这个还没有弄懂。

import Vue from 'vue'

/* Vue.mixin({
  beforeRouteLeave(to, from, next) {
    //   全局触发此事件
    //下面是条件
      if(to.name === 'regionalStatistics' && from.name === 'enterpriseQuery') {
        if(this.$vnode.parent && this.$vnode.parent.componentInstance.cache) {
        let key = this.$vnode.key == null
                            ? this.$vnode.componentOptions.Ctor.cid + (this.$vnode.componentOptions.tag ? `::${this.$vnode.componentOptions.tag}` : '')
                            : this.$vnode.key;   // 当前关闭的组件名
        let cache = this.$vnode.parent.componentInstance.cache  // 缓存的组件
        let keys = this.$vnode.parent.componentInstance.keys  // 缓存的组件名
            if(cache[key] != null) {
            
                delete cache[key]
                let index = keys.indexOf(key)
                if(index > -1) {
                keys.splice(index, 1)
                }
            }
        }
      }
    next()
  }
})
 */

3>

其实使用scrollBehavior 弊端是很大的,就是它设置的只能是body的滚动距离,还有另外一种方法:
使用@scroll 也可以监听元素滚动,并且记录下来。在页面渲染时再赋值于元素滚动距离。
@scroll可以肉眼看到滚动条滚动到指定位置,肯定没有scrollBehavior 效果好。
但是。。。我最后用了@scroll,我败在了mint-ui的上拉加载组件上。。

<div class='scrollList' @scroll="scroll">
------------------------------------------------------------------------------
 /* 滚动 */
            scroll() {
                let height = document.getElementsByClassName('scrollList')[0].scrollTop
                sessionStorage.setItem('TFD_HEIGHT',JSON.stringify({h:height}));
            },

------------------------------------------------------------------------------

   activated() {
        setTimeout(() => {
            let num = JSON.parse(sessionStorage.getItem('TFD_HEIGHT'))
            document.getElementsByClassName('scrollList')[0].scrollTop = num.h
        },100)
    },

4>

chorme有一个插件 vue Devtools,其中有一个功能可以查看缓存组件,网上有很多安装的文章。


image.png

最后的最后,用了这么多纸只为了kepp-alive,还没有达到预期


image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,816评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,729评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,300评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,780评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,890评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,084评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,151评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,912评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,355评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,666评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,809评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,504评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,150评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,121评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,628评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,724评论 2 351