zoukankan      html  css  js  c++  java
  • Vue + better-scroll 实现顶部固定字母标题

    在做移动端开发时,有时需要用到类似于下图所示的场景,一个城市列表的页面滚动效果,或者是类似的页面效果。为了实现更好的用户体验,用户在向下滚动时,将相应的顶部字母标题固定在页面上部是很炫酷的。

    如何实现呢,主要的思路是运用 better-scroll 实时监听页面的滚动坐标,当 Y 轴坐标变化时,计算当前Y轴的坐标所在的字母区间。举个例子,假如 B 字母区间底端距离页面顶端的高度为 300px,C 字母区间的底端距离页面顶端的高度为 400px,那么当Y轴坐标为 360px 时,顶部字母标题应该取值为 B 。依次类推,其实也并不复杂。

    下面我们来逐步实现。

    1.计算每组城市区间高度

    需要用到的变量:

    cityHeightList: [], // 城市区间列表列表高度
    _caclHeight() {
    // 当前城市 + 热门城市高度
      let height = this.$refs.locCityRef.clientHeight + this.$refs.hotCityRef.clientHeight;
      this.cityHeightList.push(height);
            
      let cityGroup = this.$refs.cityGroupRef;
      for (let item of cityGroup) {
        height += item.clientHeight;
        this.cityHeightList.push(height);
      }
    },

    this.$refs.locCityRef 为当前城市 div。this.$refs.hotCityRef 为热门城市 div。

    this.$refs.cityGroupRef 为每组城市的 div 集合,以 A 开头的城市一个 div,以 B 开头的城市一个 div...,将所有的 div 通过 v-for 循环出来。

    2.在 template 中引用 better-scroll 组件:

    <b-scroll
      class="content-scroll"
      v-show="!cityKeyword"
      ref="cityScrollRef"
      :listenScroll="listenScroll"
      :probeType="probeType"
      v-on:scroll="cityScroll"
    >
    ...
    </b-scroll>

    注: probeType 的值只有设置成 2 或者 3 ,better-scroll 才会实时监听滚动位置。

    v-on:scroll = "cityScroll" 为监听子组件的事件:

    2.1 better-scroll 组件,通过 this.$emit 将 scroll 事件派发出来,pos 为滚动的实时位置:

    //实时监听滚动事件 || 监听better-scroll滚动事件
    if(this.listenScroll) {
      let _this = this;     // pos 滚动的实时坐标 {x, y}
      this.scroll.on('scroll', pos => {
      // 向父组件派发滚动事件
       _this.$emit('scroll', pos)
      });
    }

    2.2 监听子组件派发的 scroll 事件 | 实时获取滚动的 Y 坐标

    cityScroll(pos) { this.scrollY = pos.y; },

    2.3 父组件监听 scrollY 的变化

    用到的变量 :

    topFixedTitle: '', // 顶部固定字母标题
    letterList: [],  //城市名称中包含的大写首字母

    Y 轴的实时位置与城市字母区间高度对比,找到当前顶部固定字母标题的取值。

    watch: {
      scrollY(newY) {
        (newY > 0 || -newY < this.cityHeightList[0]) && (this.topFixedTitle = '');
    
        for (let i=0; i<this.cityHeightList.length; i++) {
          let height_1 = this.cityHeightList[i];
          let height_2 = this.cityHeightList[i+1];
    
          if(-newY > height_1 && -newY <= height_2) {
            this.topFixedTitle = this.letterList[i];
          }
        }
      },
    }

    注意:子组件传递过来的沿 Y 轴向下滑动的位置值是负的,因此我们用 -newY 取正值后与高度进行比较。

    3.顶部固定字母标题,在 template 中添加:

    <!-- 固定顶部字母标题 -->
    <article class="fixed-top" v-show="topFixedTitle && !isSearchCity" ref="topTitleRef">
      {{ topFixedTitle }}
    </article>

    CSS:

    .fixed-top {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      background: #f2f2f2;
      height: 8vw;
      line-height: 8vw;
      padding-left: 2.5vw;
    }

    到这里我们就完成啦。如果文章中有不正确的地方,欢迎大家留言指正。

    创作不易,若文章帮助到了大家,大家可以点击右下角的打赏按钮,请笔者喝咖啡哦。O(∩_∩)O

     

  • 相关阅读:
    mysql数据库__Jdbc直接操作__PreparedStatement__新增数据库
    GeneralUtils
    java easyExcel框架
    java8 stream流操作
    Java解析json报文案列
    如何避免空指针?
    List、Map集合的遍历方式
    java---关于多态性
    Android环境的搭建
    css+div学习
  • 原文地址:https://www.cnblogs.com/Fcode-/p/13524318.html
Copyright © 2011-2022 走看看