小程序上下翻页踩坑版

658 阅读2分钟

项目需求:需要做一个类似刷抖音一样的上滑下滑的小程序翻页效果。

小程序三种滑动
  • ScrollView
  • Swiper
  • onTouchStart、onTouchEnd
首先考虑 ScrollView

代码大致是这样:

import { ScrollView } from '@tarojs/components'
<ScrollView scrollY enhanced paging-enabled> // 后面两个属性必须且为true
    <View></View>
</ScrollView>
  1. 翻页效果其实是OK的,并且还自带最后一页滑动时,ScrollView自带方法bindscrolltolower不用计算页码,也不用判断是否是最后一页就可以自定义事件(刚好这边有个需求,滑到最后一页,切换到其他路由),只是静态页面且每个页面没有动态内容切换的时候一切都看起来那么完美,我当时内心os:也不过如此,哦耶耶耶~可以摸鱼了。
  2. 然鹅当我把每一页的动态内容及逻辑都写上的时候,问题就出现了。真机开始出现各种闪屏(模拟器不会)。我猜测大概原因是因为:每一页的内容切换涉及到了页面重绘,导致渲染问题,真机就会闪屏(也只是猜测)。
  3. 并且获取每一页页码非常麻烦需要监听bindscroll感觉这方法很笨,但又没有可以替换的方法,并且这个不断的监听来改变页码,也有可能是导致页面重绘的主要原因,因为页码存在state里,改变的时候会更新视图,从而达到切换页面的效果。所以换了下一种翻页方法“Swiper”
尝试 Swiper
import { Swiper, SwiperItem } from '@tarojs/components'
  constructor() {
    this.state = {
        currentPage: 1
    }
  }

change(e) {
    let currentPage = e.detail.current // 页面
    this.setState({currentPage: currentPage})
}

<Swiper vertical bindchange={this.change} >
    {currentPage == 1 && <SwiperItem></SwiperItem>}
    {currentPage == 2 && <SwiperItem></SwiperItem>}
    {currentPage == 3 && <SwiperItem></SwiperItem>}
</Swiper>
  1. 模拟器效果基本没啥大的变化,于是真机调的时候,简直是卡的滑都滑不动~并且每一页的动画还有闪屏(动画用的animation写的,有的gif,有的精灵图..)
  2. 最后一页滑动的事件需要自己加判断手写,加上卡顿,于是又想其他方法
手写滑动 onTouchStart、onTouchEnd监听滑动(最后采用的这一种)

大致代码如下:

-- js
constructor() {
    this.state = {
      currentPage: 1,
      translateNum: 0, // 滑动距离
    }
    this.ScrollY = 0
}
// 监听滑动开始事件
handleStart(e) {
    // isShowRewardDialog这个是滑动层上有弹窗也需要滑动的话,解决滑动穿透
    const { isShowRewardDialog } = this.state
    if (isShowRewardDialog) {
      return
    }
    // 将初始滑动距离保存下来
    this.ScrollY = e && e.changedTouches && e.changedTouches[0].pageY
}
// 监听滑动结束事件
handleEnd(e) {
    // isShowRewardDialog这个是滑动层上有弹窗也需要滑动的话,解决滑动穿透
    const { isShowRewardDialog } = this.state
    if (isShowRewardDialog) {
      return
    }
    const { currentPage } = this.state
    let y = e && e.changedTouches && e.changedTouches[0].pageY
    let yValue = y - this.ScrollY
    if (yValue > 80) {
      console.log('下拉, 上滑, 页面减少')
      // currentPage控制页面显示隐藏,translateNum控制页面滚动多少vh,默认translateNum为0
      this.setState({ currentPage: currentPage - 1, translateNum: currentPage - 1 })
    }
    if (yValue < -80) {
      console.log('上拉, 下滑, 页面增加')
      this.setState({ currentPage: currentPage + 1, translateNum: currentPage + 1 })
    }
}

-- html
<View className='content' onTouchStart={this.handleStart} onTouchEnd={this.handleEnd}>
<View style={`transform: translateY(-${translateNum * 100}vh); transition: all 0.4s `} className={sysInfo && sysInfo.windowHeight >= 750 ? 'scroll' : 'scroll small'}>
    {currentPage == 1 && <View className="page page1"></View>}
    {currentPage == 2 && <View className="page page2"></View>}
    {currentPage == 3 && <View className="page page3"></View>}
</View>
</View>

完美解决以上闪屏问题,果然还是要手写!!!浅看下结果:

飞书20230302-160712 (3).gif