移动端局部滚动、标题吸顶、监听滚动

一直以来我的脑子里有一种执念(大约是2016年开始的),就是移动端无法做局部滚动,即对一个 div 设置 overflow: scroll 是无法滚动,所以才有了像 iScroll 、 Better-scroll 这样的库,但现在已经是 9012 年了,我发现移动端局部 滚动已经支持的很好了

问题介绍

最近碰到一个这样的需求,如下图所示:一个列表左侧边栏固定,右边内容部分可以滚动,同时上测标题栏可以吸顶

想法:

  • 将整个区块分为上下两部分,上侧可以在吸顶的时候做 fixed 处理,然后每个区块再分为左右两部分,用 flex 布局,左侧固定宽度,右侧flex: 1占据剩余宽度。
  • 右侧滚动区域可以用better-scroll做滚动处理,然后由于吸顶部分和内容分开,所以需要实例化两个BScroll实例。然后当任意一个实例滚动时需要监听其scroll事件,让另一个实例也滚动到 相应的scrollLeft位置,在ios、安卓浏览器上都可以很完美的运行。但由于我们是hybird开发模式,拿到native上运行就有问题了(如图所示,我们的页面是嵌在新闻、赛程、球员、数据...下的,每个tab就是一个webview,tab之间支持手势左滑右滑,这个时候用better-scroll滚动时,就会触发native的slider事件,tab就被切换掉了,导致内容无法被滑动查看,后期找native开发人员请教下是怎么处理slider事件的)

解决方法

  • 用原生scroll滚动 ,右侧元素设置overflow: scroll; -webkit-overflow-scrolling: touch; (ios惯性滚动),然后监听wrap的scroll事件
  • ios: 体验完美,在wrap范围内滚动不会触发native slide事件,并且有很好的边界回弹效果,出现滚动条,
  • 安卓:滚动也很流畅,但没有边界回弹效果并且当滚动到某一侧边界时依旧会触发native slide事件,不会出现滚动条

伪代码

  • React 代码演示
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    componentDidMount() {
    // 标准模式和混杂模式的窗体滚动元素的获取
    this.windowEl = document.scrollingElement || document.documentElement
    this.titleTop = this.titleRef.offsetTop
    window.addEventListener('scroll', () => this.wScroll())
    }
    // 吸顶处理
    wScroll() {
    if (this.windowEl.scrollTop == this.titleTop) {
    this.titleRef.classList.add('fixed')
    }
    }
    handleScroll = e => {
    let left = e.target.scrollLeft
    this.titleRef.scrollLeft = left
    };
    /**
    监测捕获阶段的事件
    onScroll 这都位于React合成事件,处于冒泡阶段
    此处其实也可以绑定 wrap 的原生scroll事件
    各种阶段事件触发的顺序:捕获 -> 冒泡 -> 原生 addEventListener('scroll')
    */
    render() {
    return (
    <>
    <div className="title" ref={ref=>this.titleRef=ref}>
    <ul className="list">...</ul>
    </div>
    <div
    className="wrap"
    onScrollCapture={this.captureScroll}
    >
    <ul className="list">...</ul>
    </div>
    </>
    );
    }

    ------------
    css

    .title, .wrap {
    overflow: scroll;
    -webkit-overflow-scrolling: touch;
    }

关于使用局部滚动出现的一些问题的处理方法


评论