vue 列表内容详情返回定位&返回顶部

详情返回定位

本文中的详情返回定位,只针对于mand-mobile组件的运用中的一些处理,仅做学习记录。其他组件可能无需考虑auto-reflow属性的影响。

使用场景: 使用mand-mobile组件实现的列表的分页展示,大概的HTML代码如下,为了实现点击单行数据,跳转详情页,从详情也返回后,页面不刷新,位置仍然为跳转前的显示位置。

//滚动区域
<md-scroll-view class="scroll" ref="scrollView" v-show="!isNoData"
  :scrolling-y="true" :scrolling-x="false" :auto-reflow="autoReflow" //注意点注意点  后面会提到
   @scroll="onScroll" @endReached="endReached" @refreshing="onRefreshing">
 //列表区域
 <md-check-group v-model="orderSelecteds" ref="group">
   <div class="orderList" v-for="(order, index) in orderList":key="order.tradeId">
       <div class="orderDetail" @click="orderDetail(order.tradeId)">
           //列表数据渲染 省略
       </div>
    </div>
  </md-check-group>
  //底部加载更多 触发分页查询
  <md-scroll-view-more slot="more" :is-finished="isFinished" ></md-scroll-view-more>
  //顶部下拉刷新
  <md-scroll-view-refresh slot="refresh" 
    slot-scope="{ scrollTop, isRefreshActive, isRefreshing }"
    :scroll-top="scrollTop" :is-refreshing="isRefreshing" :is-refresh-active="isRefreshActive">
 </md-scroll-view-refresh>
</md-scroll-view>

网上提供的方法,大概分为3种:

  • 定义一个变量
  • 利用local缓存
  • 使用vuex

思路: 在触发详情跳转前,存储当前的ScrollTop,在返回列表页时,给页面高度重新赋值。

方法1 利用beforeRouteLeave、beforeRouteEnter
在离开页面触发beforeRouteLeave时,记录当前页面滚动高度,返回页面触发beforeRouteEnter时,给document.querySelector(’.scroll’).scrollTop 重新赋值。

其中,滚动的高度可以通过(1)localStorage缓存记录,也可以通过(2)vuex commit触发改变存在state里的高度的值

  beforeRouteLeave(to, from, next) {
    if (to.name === "order_detail") {
      let scrollTop = this.$refs.scrollView.scrollY;
      console.log(scrollTop);
      
      //1.利用localStorage 存滚动距离顶部的高度
      localStorage.setItem('scrollY', scrollTop);
      
      //2.利用vuex  触发setScrollTop事件改变 scrollTop
      this.$store.commit("omsOnline/setScrollTop", scrollTop);
    } else {
      from.meta.keepAlive = false;
    }
    next();
  },
  beforeRouteEnter(to, from, next) {
  	//因为当钩子执行前,组件实例还没被创建
     // vm 就是当前组件的实例相当于上面的 this,所以在 next 方法里你就可以把 vm 当 this 来用了。
    next((vm) => {
		//1.利用 localStorage 取缓存里的值
		let scrollY = localStorage.getItem('scrollY');
		//2.利用vuex 取之前存的_scrollTop值
      	let scrollY = vm.$store.getters["omsOnline/_scrollTop"];
		
		//scrollTo  不生效  不知道为啥  hhhh
      	// vm.$refs.scrollView.scrollTo(0, scrollY, false);
      	利用document选择器取值,可以实现
      	document.querySelector('.scroll').scrollTop = scrollY;
    });
  },

以上的beforeRouteEnter 可以使用activated替代。

activated() {
    this.$nextTick(() => {
      	//1.利用 localStorage 取缓存里的值
		let scrollY = localStorage.getItem('scrollY');
		//2.利用vuex 取之前存的_scrollTop值
      	let scrollY = vm.$store.getters["omsOnline/_scrollTop"];
      document.querySelector('.scroll').scrollTop = scrollY;
    });
  },

用了上面的方法一直疑惑为什么没法通过this.$refs..scrollView.scrollTo(0, scrollY)this.$refs.scrollView.scrollY(scrollY)来改变滚动的位置,始终没有效果,想着可能是当前的mand-mobile组件有其他的事件影响了,也可能是层级有问题吧。

后来研究mand-mobile 组件中ScrollView的一些内置方法,想到可能是这个方法影响了,详情页返回是,内容发生变化,自动滚动至页面最上方。
在这里插入图片描述
最初auto-reflow的值为true,后来改为了false,果然可以定位到原来数据的位置了。

但是又引发了另一个问题,因为数据是分页的,并且可以进行数据的过滤筛选,加载分页数据后,再次触发筛选,页面下方会出现空白,没办法将筛选出来的数据正确的从顶部开始显示,也没办法及时的显示出‘加载更多’的字样,从而出现断层的空白页。

所以auto-reflow不能写死,需要动态控制。在触发分页时,将auto-reflow设为false,保证详情返回的定位正确,在触发筛选前,将auto-reflow设为true,保证页面滚动区域自动重置。

	//下拉加载更多
    endReached() {
      if (this.isFinished) {
        return;
      }
      //下拉之后,自动重置滚动区域 设为false  否则详情返回会自动回到顶部
      this.autoReflow = false;
      this.query.pageIndex++;
      this.getOrder();
    },
 	//获取默认参数
    getDefaultParam() {
      //过滤筛选时,自动重置滚动区域 设为 true, 否则下拉会出现空白
      this.autoReflow = true;
      this.$refs.scrollView.scrollTo(0, 0);
      	//------------
	 	//省略其他内容
	 	//------------
    }

对于记录和定位,我是用的是最偷懒的一种方法,定义一个变量scroll ,暂存页面内滚动后距离顶部的距离。
在跳转详情事件中:记录scroll

  orderDetail(tradeId) {
    //获取当前滚动的高度
    let scrollTop = this.$refs.scrollView.scrollY;
    //赋值给定义的变量,暂存
    this.scroll = scrollTop;
    //跳转详情页面
    this.$router.push({
      path: "/oms-online/orderDetail",
      query: {
        tradeId: tradeId,
      },
    });
  },
 activated() {
   this.$refs.scrollView.scrollY = this.scroll;
 },

返回顶部

既然做了下拉返回的功能,顺便做了个‘返回顶部’的小功能。
父组件:

//返回顶部子组件
<jk-back-top v-if="isShowBack" :scrollTop="scrollTop"></jk-back-top>

通过isShowBack判断是否显示返回顶部的图标,这时需要监听滚动区域距离顶部的高度。

md-scroll-view class="scroll" ref="scrollView"
  :scrolling-y="true" :scrolling-x="false :auto-reflow="autoReflow"
  @scroll="onScroll"  //滚动事件
>

滚动事件记录scrollTop 高度

//滚动事件
 onScroll({scrollLeft, scrollTop}) {
   this.scrollTop = scrollTop;
 },

监听scrollTop的最新值,到大于200时,显示‘返回顶部’的图标

  watch: {
    scrollTop(top) {
      if(top > 200){
        this.isShowBack = true;
      } else {
        this.isShowBack = false;
      }
    }
  },

子组件:

<template>
  <div>
    <img src="@/utils/oms-online/images/backTop.png" alt="" @click="backTop" />
  </div>
</template>

<script>
export default {
  components: {},
  data() {
    return {
      scrollTrigger: false,
    };
  },
  props: {
    scrollTop: Number,
  },
  methods: {
    backTop() {
      //无动画直接到达顶部
      //this.$parent.$refs.scrollView.scrollTo(0, 0);  
      let that = this;
      // 防止用户频繁点击返回顶部按钮,待返回顶部成功后设置scrollTrigger为初始值
      if (that.scrollTrigger) {
        return;
      }
      // 获取当前距离顶部的数值,设置每次上滑的高度直到滚动到顶部为止
      let scrollTop = this.scrollTop;
      let steep = scrollTop / 200;
      let timer = setInterval(() => {
        that.scrollTrigger = true;
        // 上滑滚动的速度慢慢加快,第一次走200/1,然后减去已走的距离,下一次用剩下的距离再减去步进值,步进值也是不断变化,这样速度会越来越快
        scrollTop -= steep;
        // 步进值不改变的话会匀速缓慢上滑,不断增加步进值上滑的距离增加,视觉效果速度变快
        steep += 5;
        if (scrollTop <= 0) {
          clearInterval(timer);
          that.scrollTrigger = false;
        }
       	//this.$parent.$refs.scrollView.scrollY(scrollTop);  不生效 不知道为啥 红红火火恍恍惚惚
        this.$parent.$refs.scrollView.scrollTo(0, scrollTop);
      }, 30);
    },
  },
};
</script>

<style lang="less">
img {
  position: fixed;
  right: 0;
  bottom: 10%;
  width: 0.64rem;
  height: 0.64rem;
  background: #f5f5f6;
  z-index: 2;  //设置层级在上层
}
</style>
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值