背景
在完成一个返回顶部的组件时,我想在组件内部直接获取到当前页面的滚动距离,并且暴露出一个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的生命周期
总结
在这里可以看到,通过重写页面的生命周期可以实现很多更加好用的组件或方法,例如:吸顶组件、倒计时组件,你都需要在页面滚动、销毁的时候去做一些逻辑处理,如果不重写页面的生命周期,会导致使用起来非常的不便,要重复的去做一下处理,但是把这些处理放到自己的组件或方法里面去执行,就能够保证组件或方法非常的好用,更加的复用。
最后
这就是如何在微信小程序上获取页面的滚动距离,如果要获取页面的其他生命周期或函数,都是类似的一个逻辑,觉得有帮助到的小伙伴请动动你的小手点点赞呢👍!