# uni-refresh-box

自定义下拉刷新组件

本 Component 是 uni ext component,需下载插件:uni-refresh-box

自定义下拉刷新组件。

本组件封装了 scroll-view/list-view等滚动容器的下拉刷新功能,使用者只需在滚动容器中加入本组件,设置组件的属性和样式,即可实现自定义下拉刷新功能。

本组件自带一个全平台通用的下拉刷新样式,即左边一个 loading 圈,右边为下拉刷新相关的文字。也提供了各种自定义方法,包括文字、样式,甚至通过插槽传入完全不同的自定义下拉效果。

# 基本用法

<template>
  <scroll-view
  style="flex: 1;"
  :refresher-enabled="true"
  :refresher-triggered="refreshing1"
  refresher-default-style="none"
  :refresher-threshold="45"
  refresher-max-drag-distance="200px"
  @refresherpulling="onRefresherpulling1"
  @refresherrefresh="onRefresherrefresh1"
  @refresherrestore="onRefresherrestore1"
  @refresherabort="onRefresherabort1"
>
  <!-- 列表内容 -->
  <view v-for="i in listCount1" :key="i" class="content-item">
    <text class="text">item-{{ i }}</text>
  </view>

  <!-- refresher 插槽使用 uni-refresh-box 组件 -->
  <uni-refresh-box
    slot="refresher"
    :pulling-distance="pullingDistance1"
    :refreshing="refreshing1"
  ></uni-refresh-box>
</scroll-view>
</template>

<script setup lang="uts">
const listCount1 = ref(3)
const refreshing1 = ref(false)
const pullingDistance1 = ref(0)

function onRefresherpulling1(e: RefresherEvent) {
  pullingDistance1.value = e.detail.dy
}

function onRefresherrefresh1() {
  refreshing1.value = true
  console.log('列表1 触发刷新')
  setTimeout(() => {
    listCount1.value += 5
    refreshing1.value = false
    console.log('列表1 刷新完成')
  }, 1500)
}

function onRefresherrestore1() {
  pullingDistance1.value = 0
}

function onRefresherabort1() {
  pullingDistance1.value = 0
}
</script>

# state 状态说明

说明
0 下拉中(未达到阈值)
1 松手可刷新(已达到阈值)
2 刷新中
3 刷新完成
4 归位中(不显示文字)

# Slots

名称 说明 插槽参数
loading 自定义图标 -

# 兼容性

Web 微信小程序 Android Android(Vapor) iOS iOS(Vapor) HarmonyOS HarmonyOS(Vapor)
5.07 5.07 5.07 x 5.07 x 5.07 5.07

# 属性

名称 类型 默认值 兼容性 描述
pullingDistance number 0 - 当前下拉距离(px),通常由外部 scroll-view 的 refresher 状态传入
refreshing boolean false - 是否正在刷新中,外部控制;为 true 时显示 loading 动画
threshold number 45 - 触发刷新的下拉阈值(px),下拉距离超过该值时进入“松手刷新”状态
pullingText string "下拉刷新" - 下拉过程中(未达到阈值)显示的提示文字
loosingText string "松手刷新" - 下拉超过阈值后显示的提示文字
loadingText string "正在刷新" - 刷新中显示的提示文字
completeText string "" - 刷新完成瞬间显示的提示文字,为空则不展示
textClass classString "" - 提示文字的自定义样式类
loadingClass classString "" - loading 图标的自定义样式类

# 示例

示例为hello uni-app x alpha分支,与最新HBuilderX Alpha版同步。与最新正式版同步的master分支示例另见

扫码体验(手机浏览器跳转到App直达页)

示例

<template>
  <view style="flex: 1;">
    <scroll-view
      style="flex: 1;"
      :refresher-enabled="true"
      :refresher-triggered="data.refreshing1"
      refresher-default-style="none"
      :refresher-threshold="45"
      refresher-max-drag-distance="200px"
      @refresherpulling="onRefresherpulling1"
      @refresherrefresh="onRefresherrefresh1"
      @refresherrestore="onRefresherrestore1"
      @refresherabort="onRefresherabort1"
    > <!-- TODO Android不支持bool属性,:refresher-enabled="true" 不能简写为 refresher-enabled -->
      <!-- 列表内容 -->
      <view v-for="i in data.listCount1" :key="i" class="content-item">
        <text class="text">item-{{ i }}</text>
      </view>

      <!-- refresher 插槽使用 uni-refresh-box 组件 -->
      <uni-refresh-box
        slot="refresher"
        :pulling-distance="data.pullingDistance1"
        :refreshing="data.refreshing1"
      ></uni-refresh-box> <!-- TODO web只认在组件外层使用slot="refresher",不支持组件内根元素使用-->
    </scroll-view>
		<text class="section-label">竖排暗黑自定义文字的下拉设置</text>
		<scroll-view
		  style="flex: 1;background-color: black;"
		  :refresher-enabled="true"
		  :refresher-triggered="data.refreshing2"
		  refresher-default-style="none"
		  :refresher-threshold="45"
		  refresher-max-drag-distance="200px"
		  @refresherpulling="onRefresherpulling2"
		  @refresherrefresh="onRefresherrefresh2"
		  @refresherrestore="onRefresherrestore2"
		  @refresherabort="onRefresherabort2"
		> 
		  <!-- 列表内容 -->
		  <view v-for="i in data.listCount2" :key="i" class="content-item">
		    <text class="text">item-{{ i }}</text>
		  </view>

		  <!-- refresher 插槽使用 uni-refresh-box 组件 -->
		  <uni-refresh-box
		    slot="refresher"
		    :pulling-distance="data.pullingDistance2"
		    :refreshing="data.refreshing2"
				loading-class="loading-dark"
				text-class="text-dark"
				style="flex-direction: column;height: 46px;padding-top: 6px;"
				pulling-text="继续下拉可刷新"
				loosing-text="释放后会刷新"
				loading-text="奋力加载中..."
			></uni-refresh-box> 
		</scroll-view>
		<text class="section-label">slot自定义下拉图标</text>
		<scroll-view
		  style="flex: 1;"
		  :refresher-enabled="true"
		  :refresher-triggered="data.refreshing3"
		  refresher-default-style="none"
		  :refresher-threshold="45"
		  refresher-max-drag-distance="200px"
		  @refresherpulling="onRefresherpulling3"
		  @refresherrefresh="onRefresherrefresh3"
		  @refresherrestore="onRefresherrestore3"
		  @refresherabort="onRefresherabort3"
		> 
		  <!-- 列表内容 -->
		  <view v-for="i in data.listCount3" :key="i" class="content-item">
		    <text class="text">item-{{ i }}</text>
		  </view>

		  <!-- refresher 插槽使用 uni-refresh-box 组件 -->
		  <uni-refresh-box
		    slot="refresher"
		    :pulling-distance="data.pullingDistance3"
		    :refreshing="data.refreshing3"
		  >
				<template #loading="{ state }">
				  <image
				    v-if="state == 2"
				    src="https://web-ext-storage.dcloud.net.cn/hello-uni-app-x/refresh-box-run.gif"
				    style="width: 20px; height: 20px;"
				  /> <!-- 刷新中的动图-->
				  <image
				    v-else
				    src="https://web-ext-storage.dcloud.net.cn/hello-uni-app-x/refresh-box-run.gif"
				    style="width: 20px; height: 20px;"
				  /> <!-- 非刷新中的图,可以和刷新中的图是一张,也可以分开-->
				</template>
				<!-- <image src="https://web-ext-storage.dcloud.net.cn/hello-uni-app-x/refresh-box-run.gif" style="width:20px;height:20px;"></image> -->
			</uni-refresh-box> 
		</scroll-view>
		<text class="section-label">无文字,纯loading</text>
		<scroll-view
		  style="flex: 1;"
		  :refresher-enabled="true"
		  :refresher-triggered="data.refreshing4"
		  refresher-default-style="none"
		  :refresher-threshold="45"
		  refresher-max-drag-distance="200px"
		  @refresherpulling="onRefresherpulling4"
		  @refresherrefresh="onRefresherrefresh4"
		  @refresherrestore="onRefresherrestore4"
		  @refresherabort="onRefresherabort4"
		> 
		  <!-- 列表内容 -->
		  <view v-for="i in data.listCount4" :key="i" class="content-item">
		    <text class="text">item-{{ i }}</text>
		  </view>

		  <!-- refresher 插槽使用 uni-refresh-box 组件 -->
		  <uni-refresh-box
		    slot="refresher"
		    :pulling-distance="data.pullingDistance4"
		    :refreshing="data.refreshing4"
				pulling-text=""
				loosing-text=""
				loading-text=""
				loading-class="loading-big-font"
		  ></uni-refresh-box> 
		</scroll-view>
  </view>
</template>

<script setup lang="uts">
type Data = {
  listCount1: number
  refreshing1: boolean
  pullingDistance1: number
  listCount2: number
  refreshing2: boolean
  pullingDistance2: number
  listCount3: number
  refreshing3: boolean
  pullingDistance3: number
  listCount4: number
  refreshing4: boolean
  pullingDistance4: number
}

const data = reactive<Data>({
  listCount1: 3,
  refreshing1: false,
  pullingDistance1: 0,
  listCount2: 3,
  refreshing2: false,
  pullingDistance2: 0,
  listCount3: 3,
  refreshing3: false,
  pullingDistance3: 0,
  listCount4: 3,
  refreshing4: false,
  pullingDistance4: 0
})

function onRefresherpulling1(e: RefresherEvent) {
  data.pullingDistance1 = e.detail.dy
}

function onRefresherrefresh1() {
  data.refreshing1 = true
  console.log('列表1 触发刷新')
  setTimeout(() => {
    data.listCount1 += 5
    data.refreshing1 = false
    console.log('列表1 刷新完成')
  }, 1500)
}

function onRefresherrestore1() {
  data.pullingDistance1 = 0
}

function onRefresherabort1() {
  data.pullingDistance1 = 0
}

function onRefresherpulling2(e: RefresherEvent) {
  data.pullingDistance2 = e.detail.dy
}

function onRefresherrefresh2() {
  data.refreshing2 = true
  console.log('列表2 触发刷新')
  setTimeout(() => {
    data.listCount2 += 5
    data.refreshing2 = false
    console.log('列表2 刷新完成')
  }, 1500)
}

function onRefresherrestore2() {
  data.pullingDistance2 = 0
}

function onRefresherabort2() {
  data.pullingDistance2 = 0
}

function onRefresherpulling3(e: RefresherEvent) {
  data.pullingDistance3 = e.detail.dy
}

function onRefresherrefresh3() {
  data.refreshing3 = true
  console.log('列表3 触发刷新')
  setTimeout(() => {
    data.listCount3 += 5
    data.refreshing3 = false
    console.log('列表3 刷新完成')
  }, 1500)
}

function onRefresherrestore3() {
  data.pullingDistance3 = 0
}

function onRefresherabort3() {
  data.pullingDistance3 = 0
}

function onRefresherpulling4(e: RefresherEvent) {
  data.pullingDistance4 = e.detail.dy
}

function onRefresherrefresh4() {
  data.refreshing4 = true
  console.log('列表4 触发刷新')
  setTimeout(() => {
    data.listCount4 += 5
    data.refreshing4 = false
    console.log('列表4 刷新完成')
  }, 1500)
}

function onRefresherrestore4() {
  data.pullingDistance4 = 0
}

function onRefresherabort4() {
  data.pullingDistance4 = 0
}

defineExpose({
  data
})
</script>

<style>
.section-label {
  margin: 5px;
  color: var(--text-color, #333333);
}
.content-item {
  margin: 5px 10px;
}
.text {
  color: var(--text-color, #333333);
  font-size: 14px;
}

.loading-dark{
	border-color:white;
	width: 20px;
	height: 20px;
}
.text-dark{
	color: white;
	margin-top: 5px;
}

.loading-big-font{
	width: 24px;
	height: 24px;
}
</style>

# 参见