使用wxs实现一个好用的下拉刷新
啥都不说,先上一张效果图:
image可能有点糊但是因为图床关系,文件不能超过1m,所以各位将就一下就好。
下面开始介绍如何使用wxs来实现一个自定义的下拉刷新。
前言
要想实现wxs的下拉刷新,首先我们需要为什么我们需要这么做,为啥需要wxs
呢? 这个东西究竟有啥用呢? 所以在开始之前,我们就先来简单介绍一下wxs是什么。
wxs
wxs的出现,根据官方文档中的描述,是为了处理2个页面之间的频繁交互,导致事件不停的传递从而出现的性能影响问题。
举个例子: 现在有A页面和B页面,A页面touchmove
手势会伴随着B页面也跟着移动,所以一次touchmove
的响应过程是:
-
touchemove
事件从视图层 传递到 逻辑层 - 逻辑层处理了
touchmove
的行为后 再通过setData
来改变B的位置(即又从逻辑层传递到了视图层)
一次 touchmove 的响应需要经过 2 次的逻辑层和渲染层的通信以及一次渲染,通信的耗时比较大。此外 setData 渲染也会阻塞其它脚本执行,导致了整个用户交互的动画过程会有延迟
而wxs就是为了减少页面间的通讯,让事件再视图层响应。在这里又需要引申出一点,就是小程序的框架结构。
image而我们使用wxs的目的就是为了让代码直接运行才视图层中,如下图:
image开始实现
讲完了上面的基础知识,现在开始编写代码来实现我们想要的效果
- 首先,我们需要在
components
文件中新建一个wxs
文件。结构目录如下:
然后我们首先来编写components
中的逻辑代码
//components dropdown.wxml
<scroll-view
style="height:400px"
scroll-y="{{true}}"
bind:touchstart="{{scroll.touchStart}}"
bind:touchmove="{{scroll.touchmove}}"
bind:touchend="{{scroll.touchend}}"
>
<view class="container" change:prop="{{scroll.completeRefresh}}" prop="{{isCompleteRefresh}}">
<view class="dropdown">
<view class="loading-icon" ></view>
</view>
</view>
<slot></slot>
</scroll-view>
我们先来分析一下上面的代码:
-
首先我们在最外层用一个
scrollView
标签包裹,是为了能够使用对应的事件,这里需要主要,scroll-view
必须要规定好高度,我这里为了方便测试,所以写死,真实开发的时候可以把他作为一个参数传进来。 -
这一点比较核心,我们可以看到我们使用了
change:prop
和prop
这两个属性。这里的意思其实就是每当prop
(也就是组件接收到新得传参的时候),就会触发change:prop
绑定的对应的方法。我们这里绑定的是wxs
中的方法。 -
slot
就是我们用来存放你的正常页面内容的地方。
我们接着来编写最关键的wxs
部分
// components dropdown.wxs
var touchStartPosition = 0; // 开始的位置
var touchMoveDistance = 0; // 下拉的距离
var touchMoveMaxDistance = 0; //下拉的最大距离(阈值)
var isLoading = false; // 当前是否处于下拉刷新状态 (锁)
var touchStart = function (event, ownerInstance) {
if(isLoading){
return false
}
// 设置手指刚点下去的位置的值
touchStartPosition = event.touches[0].clientY
touchMoveDistance = 0
}
var touchMove = function(event, ownerInstance) {
// 记录下拉的距离
touchMoveDistance = event.touches[0].clientY - touchStartPosition
// 此时手指是向上移动,直接拦截
if(touchMoveDistance <= 0){
return false
}
// 正在刷新也退出
if(isLoading) {
return false
}
// 达到指定要求的阈值
if(touchMoveDistance >= (touchMoveMaxDistance * 1.4)) {
// 改变指定对象的样式
ownerInstance.selectComponent('.dropdown').setStyle({
// *1.4 是为了让下拉可以跟着手指移动超出阈值要求的部分,让效果看起来有弹性
top: touchMoveMaxDistance * 1.4 + 'px'
})
} else {
// 如果没有超出极限距离,则直接移动到指定阈值的位置
ownerInstance.selectComponent('.dropdown').setStyle({
top: touchMoveDistance + 'px'
})
}
return false
}
var touchEnd = function (event, ownerInstance) {
if(isLoading) {
return false
}
// 如果往下滑结束行为
if(touchMoveDistance <= 0){
return false
}
// 下拉距离并没到达阈值
if(touchMoveDistance < touchMoveMacDistance ) {
ownerInstance.selectComponent('.dropdown').setStyle({
transition: 'all .8s',
top: '0px'
})
} else {
// 开始刷新
isLoading = true
ownerInstance.selectComponent('.dropdown').setStyle({
transition: 'all .8s',
top: touchMoveMaxDistance + 'px'
})
// 调用外部组件的方法(即执行相应的下拉刷新操作)
ownerInstance.callMethod('dropLoading')
}
// 重置
touchStartPosition = 0
}
var completeRefresh = function(newValue, oldValue, ownerInstance) {
// 执行完相应的下拉刷新操作之后,会被调用并且重置样式。
ownerInstance.selectComponent('.dropdown').setStyle({
transition: 'all .8s',
top: '0px'
})
initFunction()
}
var initFunction = function () { // 重置函数
touchStartPosition = 0;
touchMoveDistance = 0;
touchMoveMaxDistance = 80;
isLoading = false
isRefreshLower = false
}
module.exports = {
touchStart: touchStart,
touchMove: touchMove,
touchEnd: touchEnd,
completeRefresh: completeRefresh,
}
小结
上面的代码有点多,但是其实注释已经写得十分清晰了。其实需要处理得流程就是分为三步:
- 手指刚触碰屏幕得时候
这个时候需要记录手指的初始位置,以便后面的操作进行
- 手指在屏幕移动得时候
此处逻辑最多,主要是根据前面拿到的位置判断对比,主要是动画的执行(橡皮筋动画)
- 手指离开屏幕的时候
最终手指离开的位置,是否达到阈值,调用外部方法,并且执行相应得动画
上面讲完了主要得逻辑代码之后,下面的内容就比较容易了,主要围绕着如何使用来展开,咱们继续
我们的components
还差最后一步就完成了,那就是编写js
和wxss
。我们还是贴上代码,并且在注释中对代码进行解析
// 设置传参的值,这个值也是wxml 中 change:prop 监听的值
properties: {
// 完成下拉刷新
isCompleteRefresh:{
type:Boolean,
},
},
//.... data
method:{
// 这里的dropLoading 就是 wxs 中 callMethod 调用的方法
dropLoading(){
// 暴露一个接口,让外面请求
this.triggerEvent('dropLoading')
},
}
/* components dropdown.wxss */
/* 这里没啥好讲的,直接上代码就好了 */
.container {
width: 100%;
z-index: 9999;
transition-timing-function: ease;
}
.dropdown {
position: absolute;
top: 0px;
width: 100%;
height: 80px;
display: flex;
align-items: center;
justify-content: center;
transform-origin: top center;
background: transparent;
transform: translateY(-100%) ;
}
.loading-icon{
width: 20px;
height: 20px;
border: 3px solid;
border-color: #f59a23 #f59a23 #f59a23 transparent;
border-radius: 100%;
animation: scale 1s linear infinite;
}
@keyframes scale {
100%{
transform: rotate(360deg);
}
}
以上就完成了components
组件部分的开发,下面我就到index
中进行使用了。马上就要完成!
-
首先我们需要在
json
文件中注册组件,这里就不贴代码了,你们应该能明白 -
然后我们在
wxml
文件中调用组件
<view class="container">
<view class="header" style="height:100px;"></view>
<dropdown
bind:dropLoading="dropdownRefresh"
isCompleteRefresh="{{isCompleteRefresh}}">
<view class="content">
// 页面内容 slot中插入
</view>
</dropdown>
</view>
最后再在js中配置对应需要调用的方法
dropdownRefresh(){
console.log('下拉刷新中....')
setTimeout(res=>{
// 放你的逻辑代码
console.log('刷新完成了..')
this.setData({
isCompleteRefresh:true
})
},3000)
}
这样就大功告成了!
以上就是利用wxs实现自定义的下拉刷新的全部流程。感谢您的阅读,如有说得不好的地方还请您多多包涵
以上
网友评论