美文网首页
keep-alive 缓存

keep-alive 缓存

作者: 小北呀_ | 来源:发表于2020-01-17 17:17 被阅读0次

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

    必要的因素:

    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

    相关文章

      网友评论

          本文标题:keep-alive 缓存

          本文链接:https://www.haomeiwen.com/subject/cwthzctx.html