我想来想去,可能是布局的问题,或者是过渡动画导致的,元素的scroll无法记住。

我尝试给html,body,和最外围的父元素隐藏滚动条,然后只给内容的容器元素设置滚动条,结果切换的时候还是无法记住。

实在没辙,只能用点强迫办法了,就是在路由出去之前记住当前容器的滚动条高度,然后进入的时候延迟一点点时间,再恢复,为什么要延迟呢,这个主要是因为动画的问题。

在需要记住滚动条高度的路由页面使用路由守卫:

//离开之前保存scrollTop
beforeRouteLeave(to, from, next) {
    //保存滚动条元素div的scrollTop值
   this.scrollY = document.querySelector('.container').scrollTop
    next();
}

获取到当前页面的容器,然后获取容器的高度,保存在data的scrollY 中,

进入路由时

beforeRouteEnter(to, from, next) {
    next(vm => { // vm = this
        document.querySelector('.container').scrollTop = vm.scrollY
    })
},

通过next里面的vm来获取当前页面的this,然后来设置容器的高度。

然后就简单了,我们可以给所有的路由页面,需要记录高度的容器设置一个class为container,然后方法都是一样的了。

基本的做法就是这样,但是我发现使用了过渡动画后,这效果并不会有效,最后我根据我自己的项目的过渡动画时间做了300ms的延迟,然后就可以了

beforeRouteEnter(to, from, next) {
    next(vm => { // vm = this
      setTimeout(() => {
          document.querySelector('.container').scrollTop = vm.scrollY
        }, 300);
        
    })
},

优化

这样写的话,很多的东西都重复了,比如变量scrollY,相同的方法,所以,我们可以使用mixins来减少代码书写,然后将方法都封装到methods里面,使用的时候调用就行了。

并且调用的methods的时候,在进入路由的时候,使用vm.xxx()运行的xxx方法时,是可以在这个方法里面使用this来访问上下文的。这一点非常好。

我自己的封装

mixins

export default {
  data() {
    return {
      scrollY: null,
      scrollContainer: null
    }
  },
  methods: {
    saveScrollY(container) {
      this.scrollY = container.scrollTop;
      this.scrollContainer = container;
    },
    restoreScrollY(that) {
      if (that.scrollY && that.scrollContainer) {
        //300是用于动画延时,不然scroll动不了
        setTimeout(() => {
          that.scrollContainer.scrollTop = that.scrollY;
        }, 300);
      }
    }
  }
}

vue页面调用

<script>
import scrollY from "@/mixins/scrollY";
export default {
  mixins: [scrollY],
  //离开之前保存scrollTop
  beforeRouteLeave(to, from, next) {
    //保存滚动条元素div的scrollTop值
    this.saveScrollY(this.$refs.homeContainer);
    next();
  },
  //回来的时候恢复滚动
  beforeRouteEnter(to, from, next) {
    next(vm => {
      vm.restoreScrollY(vm);
    });
  }
};
</script>
分类: vue 项目实战 标签: keep-alive滚动条

评论

暂无评论数据

暂无评论数据

目录