完全自定义的带有下拉刷新的scroll-view组件.md 6.38 KB
Newer Older
huahua committed
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
## 完全自定义的带有下拉刷新的scroll-view组件

​	看到很多人都需要下拉刷新的scroll-view组件 , 也有很多是从自己项目中抽离出来的组件 . 前端不是设计师 , 而且也难以定制样式 , 授人🐟不如授之以渔 , 所以我这边写了一个基于scroll-view的带下拉刷新的组件 . 我这边只封装了逻辑和进行优化组件的性能 . 

​	大致说明下效果 下拉时遵循一个 ease-in-out曲线(慢快慢,即手滑动距离与下拉距离非线性)  , 下拉距离至超过设置值时 可以有回弹后暂停继续回弹的效果,可以参照手机QQ的下拉刷新效果 ; 过程中有钩子事件 , 你可以改变下拉框的内容和发送请求或别的事情 . 可以看gif 可能有些卡 但是实际上不是卡的(电脑端) 手机端不知道怎么样



#### 自定义属性

```Javascript
upRefresh: {
	//是否开启下拉刷新功能 , 不要动态改变这个属性
​      type: Boolean,
    
​      default: true

​    },
	//控制显示底部的提示框(可配合scrolltolower事件用于底部加载 )
​    downLoading: {

​      type: Boolean,

​      default: false

​    },

​    scrollHeight: {

​      //scroll显示区的高度(rpx)

​      type: Number,

​      default: 800

​    },

​    moveMax: {

​      //可下拉的最大距离 指手指滑动的距离(px)  超出后会被截断 此时下拉框已经完全显示 即已经到达
huahua committed
41
      //下面属性topHeight的高度
huahua committed
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192

​      type: Number,

​      default: 300

​    },

​    topHeight: {
    
​      //下拉整个框的最大的高度

​      type: Number,

​      default: 100

​    },

​    animationTime: {

​      //回弹的缓动时间 当upFresh完全显示时 需要花费300ms回弹

​      //upFresh不完全显示时 时间减少 距离曲线按照ease-in-out函数 慢->快->慢

​      type: Number,

​      default: 300

​    },

​    interruptPosition: {
​      //回弹中断时的高度(px),同时判断是否下拉成功钩子的临界点 建议设置成传入提示框的高度以保持回弹暂停时文字的居中
​      type: Number,

​      default: 40

​    }
```

#### 自定义事件和下拉时的钩子

@start,@move,@end 对应touchstart,touchmove,touchend事件参数为event

**注意这些事件判断标准都是下拉的高度 , 而不是手指移动的距离**

**重要!**

##### @pushToInterrupt 下拉达到interruptPosition就会触发这个钩子 下拉过程中只会执行一次

##### @interrupt 回弹暂停的钩子,此时高度为interruptPosition,参数为解除回弹暂停的函数

##### @finished 最后回弹结束高度为0时的钩子

#### **插槽**

```
<template slot="top"></template>
<template slot="content"></template>
<template slot="bottom"></template>
```

top对应传入提示文字内容 整个下拉框要因为要设置height的变化 所以无法移除 设置了 position:relative , 你可以 slot可以设置position:absolute来控制居中之类的 如果有有要求可以回到源码中改 比如

```html
<template slot="top">
<view :style="'position: absolute;bottom: 0px;height: ' + 40 + 'px;line-height:' + 40 + 'px;width: 100%;text-align: center;'">{{tip}}</view>
</template>
//设置 position: absolute;bottom: 0px; 可以使提示文字一直在下拉框底部
//上面提到interruptPosition建议为slot的view的高度40 以保证暂停时文字的居中
```

```html
源码
 <view
      class="transform will"
      v-if="upRefresh"
      :style="'position:relative;height:' + height + 'px;'"
    >
      <slot name="top"></slot>
    </view>
//其他样式也可自行修改 , "'height:'+height+'px'"为控制下拉框变化部分 , 不可修改
```

其他两个content即为view-scroll的内容 bottom为底部加载的内容(默认关闭)

#### 示例

```Javascript
<view class="content">
		<refresh @interrupt="interrupt" @pushToInterrupt="pushToInterrupt" @finished="finished" @scrolltolower="g">
			<template slot="top">
					<view :style="'position: absolute;bottom: 0px;height: ' + 40 + 'px;line-height:' + 40 + 'px;width: 100%;text-align: center;'">
					{{tip}}	
					</view>
			</template>
			<template slot="content">
				<view v-for="index in 5" :key="index" class="" style="height: 500px;background:#B2B2B2;border: #2C405A 1px solid;">在美国总统眼里,一切都是生意,只要是生意他不在乎用什么手段。他更喜欢用敲诈勒索,刮地三尺来榨取别国的血汗钱来实现美国的伟大。就在这段日子里,美国总统喊话日韩,要求韩国上交50亿美元保护费,要求日本支付比现在多5倍的保护费,如果不给,就等着美国的怒火吧。美国总统这种做法给了日韩很大的压力,他们在给与不给的选择上左右为难,然而有一个国家却不管美国总统的臭毛病。要求韩国上交50亿美元保护费,要求日本支付比现在多5倍的保护费,如果不给,就等着美国的怒火吧。美国总统这种做法给了日韩很大的压力,他们在给与不给的选择上左右为难,然而有一个国家却不管美国总统的臭毛病。
				</view>
			</template>
			<template slot="bottom">
				<view>
				11111111111111111111111111111111111111111111111
				</view>
			</template>
		</refresh>
	</view>
	<script>
import refresh from '@/components/refresh.vue';
export default {
	components: {
		refresh
	},
	data() {
		return {
			tip: '下拉刷新'
		};
	},
	onLoad() {},
	methods: {
		g(e){},
		interrupt(e) {
            this.tip = '刷新中'
            //模拟发送请求
			setTimeout(e, 500);
			this.tip = '刷新成功';
		},
		pushToInterrupt() {
			this.tip = '释放刷新';
		},
		finished() {
			this.tip = '下拉刷新';
		}
	}
};
</script>

<style></style>

```

(1)下拉至interrupt,tip:下拉刷新->释放刷新 

(2)回弹中断:tip->刷新中,发送请求 ,回调函数 tip->刷新成功 ,执行参数e() 回弹继续

(3)完成整个过程 tip->释放刷新

###### 其他的问题

我这边只测试了h5端和微信小程序开发者工具 , 基本上bug已经被改完了,但是注意小程序端我这边使用的是自定义组件是成功的 非自定义组件不成功 , 貌似是uniapp非自定义组件不支持多slot的原因 只显示了content的slot(再次吐槽uniapp对插槽支持度 不完善slot和slot作用域非常影响插件质量) 你可以把提示移入源码都可以的 .  视极端与否 有bug可以在下面反馈下