使用vue实现移动端h5的scroll-view

刁茂才
2023-12-01

需求:移动端h5,页面顶部有nav-bar,下部有tab-bar,缺少中间内容盒子,当tab-bar页面切换时,页面滚动位置丢失,导致交互类似页面重新渲染

根据这种需求,就衍生出了scroll-view组件,下面是我结合vant实现的简易的scroll-view

首先是tab集合页

<template>
  <section>
    <van-nav-bar :title="title" :left-arrow="false" :fixed="true" />
    <transition>
      <keep-alive>
        <home v-if="active==0"></home>
        <classify v-else-if="active==1"></classify>
        <shop-car v-else-if="active==2"></shop-car>
        <find v-else-if="active==3"></find>
        <mine v-else-if="active==4"></mine>
      </keep-alive>
    </transition>
    <van-tabbar v-model="active">
      <van-tabbar-item icon="home-o">首页</van-tabbar-item>
      <van-tabbar-item icon="apps-o">分类</van-tabbar-item>
      <van-tabbar-item icon="shopping-cart-o">购物车</van-tabbar-item>
      <van-tabbar-item icon="point-gift-o">发现</van-tabbar-item>
      <van-tabbar-item icon="user-o">我的</van-tabbar-item>
    </van-tabbar>
  </section>
</template>
<script>
import Home from "@/views/Home.vue";
import Classify from "@/views/Classify.vue";
import shopCar from "@/views/shopCar.vue";
import Find from "@/views/Find.vue";
import Mine from "@/views/Mine.vue";
export default {
  components: {
    home: Home,
    classify: Classify,
    "shop-car": shopCar,
    find: Find,
    mine: Mine
  },
  data() {
    return {
      active: 0
    };
  },
  computed: {
    title: function() {
      let title = "首页";
      switch (this.active) {
        case 0:
          title = "首页";
          break;
        case 1:
          title = "分类";
          break;
        case 2:
          title = "购物车";
          break;
        case 3:
          title = "发现";
          break;
        case 4:
          title = "";
          break;
      }
      return title;
    }
  },
  methods: {},
  mounted() {}
};
</script>
<style>
.van-nav-bar--fixed {
  background: linear-gradient(to right, #ff9700, #ed1c24);
}
.van-nav-bar__title {
  color: #fff;
}
.van-tabbar-item--active {
  color: #f65a10;
}
</style>

此页面使用keep-alive防止tab切换时导致组件被销毁

就用首页作为示例页

<template>
<div id="scroll_fa">
  <scroll-view id="scroll_box" scroll-y="true" @getScrollTop="getScrollTop" @reachBottom="onReachBottom">
    <div id="page">
      <van-pull-refresh v-model="isLoading" @refresh="onRefresh">
        <div v-for="(item,index) in 100" :key="index">this is home</div>
      </van-pull-refresh>
    </div>
  </scroll-view>
  </div>
</template>
<script>
export default {
  data() {
    return {
      isLoading: false
    };
  },
  methods: {
    onRefresh() {
      setTimeout(() => {
        this.$toast("刷新成功");
        this.isLoading = false;
        this.count++;
      }, 500);
    },
    getScrollTop(e){
      window.console.log(e)
    },
    //触底事件
    onReachBottom(){
      window.console.log('触底');
    }
  },
  mounted() {
    this.$toast("重载");
  }
};
</script>
<style scoped>
#scroll_fa{
  width: 100%;
  position: fixed;
  z-index:1;
  top: 45px;
  bottom: 50px;
}
#scroll_box{
  width: 100%;
  height: 100%;
}
#page {
  width: 100%;
  min-height: 100%;
}
</style>

scroll-view组件采用全局注册,故未在此页面引入,下面是scroll-view的代码

<template>
  <div v-bind:class="{'my_scroll_container':true}" @scroll="getScroll" :style="`${scrollX==='true'||scrollX===true?'overflow-x:scroll;overflow-y:hidden':''};${scrollY==='true'||scrollY===true?'overflow-x:hidden;overflow-y:scroll':''};`">
    <slot></slot>
  </div>
</template>
<script>
export default {
  props: {
    scrollX:{
      type:[String,Boolean],
      value:false
    },
    scrollY:{
      type:[String,Boolean],
      value:false
    }
  },
  data() {
    return {
      scrollTop: 0
    };
  },
  methods: {
    //滚动事件
    getScroll(e) {
      let wScrollY = e.target.scrollTop; // 当前滚动条位置
      this.scrollTop = wScrollY;
      let wInnerH = e.target.clientHeight; // 设备窗口的高度(不会变)
      let bScrollH = e.target.scrollHeight; // 元素总高度
      if (wScrollY + wInnerH >= bScrollH) {
        this.$emit("reachBottom");
      }
    }
  },
  activated() {
    this.$el.scrollTop = this.scrollTop;
    this.$emit('getScrollTop',{scrollTop:this.scrollTop});
  },
  updated() {},
  mounted() {}
};
</script>
<style scoped>
.my_scroll_container{
  width: 100%;
  height: 250px;
}
</style>

至此就实现了scroll-view的滚动位置记录,和触底事件

 类似资料: