微信小程序在组件中获取页面滚动距离

背景

在完成一个返回顶部的组件时,我想在组件内部直接获取到当前页面的滚动距离,并且暴露出一个props来控制超出多少距离就显示这个返回顶部的组件。功能其实很简单,只需要监听页面的onPageScroll函数获取到scrollTop即可获取到当前滚动的距离,并进行显示/隐藏的判断,但是翻遍了小程序文档都没有发现如何在组件中使用onPageScroll,于是想到了重写 页面的onPageScroll这个方法,通过重写onPageScroll就可以在组件中获取到页面的滚动距离,在此总结一下。

如何在组件中获取页面的滚动距离?

1、在组件中获取页面的onPageScroll函数

微信小程序文档上,Page的参数有一个值是onPageScroll,可以在这个回调函数中拿到页面滚动的距离

但是在组件的生命周期里面并没有这个值,wx上也没有这个函数,那这个时候就有小伙伴想到一个办法,可以通过组件通信的方式,将页面中的onPageScroll返回的scrollTop,通过组件传参的方式传递到组件中就行使用,这个方式是可以的,但是太麻烦了,又需要接收参数,又要传递参数,使用起来会让人非常的不爽,那么我们有没有办法在组件中获取到onPageScroll呢?

答案是:通过getCurrentPages这个方法来获取页面的实例

js 复制代码
    attached() {
      const pages = getCurrentPages() || [];
      let curPage = null;
      if (pages && pages.length - 1 >= 0) {
        curPage = pages[pages.length - 1];
      }
    },

在组件的attached生命周期中,调用getCurrentPages方法获取到最后一个元素,就是我们当前页面的实例,获取到实例后,让我们来打印一下:

可以看到这个获取的实例对象是有onPageScroll函数的,其实很好理解,getCurrentPages这个方法是获取当前的页面栈,返回值是一个数组,数组的最后一个值肯定就是当前所在的页面,这个值就是当前页面的实例,当然也能获取到对应的生命周期的函数。

2、重写页面的onPageScroll函数

那么我们能拿到这个函数了,怎么去重写这个函数呢?

其实这里的重写方法非常的简单,触发onPageScroll这个函数是页面滚动时触发,那么我只需要将这个函数重写为自己的函数方法就可以

js 复制代码
  // 页面滚动时触发
  curPage.onPageScroll = () => {
      console.log('页面滚动了')
  };

当你加上这句代码后,试着滚动一下页面呢,看看会不会打印这个内容呢?

打印了,一连串的页面滚动了开始打印,你是不是觉得重写难道就这么简单吗?听着这么高大上的词语,结果是这么简单的一个实现,其实不然,我们都知道onPageScroll这个函数有一个参数,可以从里面获取到scrollTop这个值,接下来你试着获取一下这个值呢?

javascript 复制代码
   // 页面滚动时触发
  curPage.onPageScroll = (rest) => {
      console.log('滚动值', rest)
  };

接下来再继续滚动页面呢?你会发现scrollTop这个值出来啦,心里默念一句博主是傻逼吧?看来重写函数真的是这么简单的一件事情啊!(请接着往下看)

好了,这个函数的重写就完成了,我们就可以在组件中直接获取页面的滚动距离,可以去组件中处理页面滚动的逻辑了,工作也做完了,可以开始摸鱼咯!

结果有一天有个同事用你这个组件,突然过来喷你,说你封的啥组件,把页面的onPageScroll搞的不执行了,然后开始对你一顿喷,请再看一下上面的代码,我们确实是重写了onPageScroll,但是由于我们重写了这个函数,导致了页面上本身的onPageScroll没有了,因为被重写在这里了,所以页面的onPageScroll就没有了,也就不会执行了。

那这里怎么办呢?其实还是很简单,利用了一下闭包的原理,我们只需要把之前的onPageScroll用一个变量存储起来就可以了,然后在重写onPageScroll时先执行这个保存起来的函数,再执行我们自己的逻辑就可以了。

js 复制代码
const pages = getCurrentPages() || [];
let curPage = null;
if (pages && pages.length - 1 >= 0) {
    curPage = pages[pages.length - 1];
}
if (!curPage) return;
const originPageScroll = curPage?.onPageScroll;
curPage.onPageScroll = (rest) => {
    originPageScroll?.call(this, rest);
    // 自己的逻辑
};

好了,没有关子卖了,真的结束了!其实完整的看下来还是会发现,真的就是这么简单!(希望不要喷我🤣🤣🤣🤣) 重写页面周期的具体逻辑可以看这个文章:微信小程序重写Page的生命周期

总结

在这里可以看到,通过重写页面的生命周期可以实现很多更加好用的组件或方法,例如:吸顶组件、倒计时组件,你都需要在页面滚动、销毁的时候去做一些逻辑处理,如果不重写页面的生命周期,会导致使用起来非常的不便,要重复的去做一下处理,但是把这些处理放到自己的组件或方法里面去执行,就能够保证组件或方法非常的好用,更加的复用。

最后

这就是如何在微信小程序上获取页面的滚动距离,如果要获取页面的其他生命周期或函数,都是类似的一个逻辑,觉得有帮助到的小伙伴请动动你的小手点点赞呢👍!

相关推荐
清灵xmf10 分钟前
TypeScript 类型进阶指南
javascript·typescript·泛型·t·infer
小白学大数据17 分钟前
JavaScript重定向对网络爬虫的影响及处理
开发语言·javascript·数据库·爬虫
qq_3901617725 分钟前
防抖函数--应用场景及示例
前端·javascript
334554321 小时前
element动态表头合并表格
开发语言·javascript·ecmascript
John.liu_Test1 小时前
js下载excel示例demo
前端·javascript·excel
Yaml41 小时前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理
PleaSure乐事1 小时前
【React.js】AntDesignPro左侧菜单栏栏目名称不显示的解决方案
前端·javascript·react.js·前端框架·webstorm·antdesignpro
哟哟耶耶1 小时前
js-将JavaScript对象或值转换为JSON字符串 JSON.stringify(this.SelectDataListCourse)
前端·javascript·json
getaxiosluo1 小时前
react jsx基本语法,脚手架,父子传参,refs等详解
前端·vue.js·react.js·前端框架·hook·jsx
理想不理想v1 小时前
vue种ref跟reactive的区别?
前端·javascript·vue.js·webpack·前端框架·node.js·ecmascript