uni-app下拉刷新魔法:给你的应用添加“焕然一新“的能力

内容分享1小时前发布
9 0 0

🌊 uni-app下拉刷新魔法:给你的应用添加”焕然一新”的能力

🌟 引言:下拉的小魔法,刷新的大世界

想象一下,你的应用就像一个魔法水晶球,用户轻轻向下拉动它,水晶球内的世界就会焕然一新!这就是下拉刷新的魔力 – 一个简单的手势,却能带来全新的体验和最新的内容。在uni-app中,这个魔法非常容易实现,只需掌握两个关键咒语:
onPullDownRefresh

stopPullDownRefresh

🎭 下拉刷新的幕后魔法


┌─────────────────────────────────────────────────────────┐
│                下拉刷新工作流程                         │
└───────────────────────────┬─────────────────────────────┘
                            │
                            ▼
                ┌─────────────────────┐
                │   开启下拉刷新功能  │
                │   (pages.json配置)  │
                └──────────┬──────────┘
                           │
                           ▼
                ┌─────────────────────┐
                │   用户下拉页面      │
                │   (触发刷新动作)    │
                └──────────┬──────────┘
                           │
                           ▼
               ┌───────────────────────┐
               │ onPullDownRefresh     │
               │ 函数自动触发          │
               └───────────┬───────────┘
                           │
                           ▼
              ┌────────────────────────┐
              │   执行数据刷新逻辑     │
              │   (API请求/数据更新)   │
              └────────────┬───────────┘
                           │
                           ▼
             ┌──────────────────────────┐
             │  刷新完成               │
             │  stopPullDownRefresh     │
             └──────────────────────────┘
                           │
                           ▼
             ┌──────────────────────────┐
             │     刷新动画结束        │
             │     页面恢复正常        │
             └──────────────────────────┘

🧙‍♂️ 两大魔法咒语详解

1️⃣ 第一咒语:启动刷新魔法
onPullDownRefresh


onPullDownRefresh
是一个神奇的生命周期函数,它就像施法者的”感应术”,能够感知用户的下拉动作并立即响应。当用户下拉页面时,这个函数会自动被触发,让你有机会施展”更新魔法”。

2️⃣ 第二咒语:结束刷新魔法
stopPullDownRefresh


uni.stopPullDownRefresh()
是终止咒语,告诉系统”刷新任务已完成”。它就像魔法仪式的结束语,让下拉动画优雅地结束,页面回到正常状态。忘记使用这个咒语,会导致刷新动画一直显示,让用户感到困惑。

🏞️ 生活类比:图书馆的魔法书架

想象你在一个魔法图书馆,面前有一个特殊的书架:

下拉书架顶部(用户下拉页面):这告诉图书管理员你想看最新的书籍管理员开始更换书籍(onPullDownRefresh触发):图书管理员收到信号,开始取下旧书,放上新书更换完成的铃声(stopPullDownRefresh):当所有新书都已上架,管理员会敲响一个小铃铛,表示”更新完成”书架恢复原位(刷新动画结束):书架滑回原来的位置,你可以浏览全新的藏书了

如果管理员忘记敲铃(忘记调用stopPullDownRefresh),书架就会一直处于”正在更新”状态,让你不知道是否可以开始浏览新书。

💻 魔法实践:代码示例

🪄 施法前的准备:开启下拉刷新功能

首先,需要在
pages.json
中为页面启用下拉刷新能力:


{
  "pages": [
    {
      "path": "pages/index/index",
      "style": {
        "navigationBarTitleText": "首页",
        "enablePullDownRefresh": true,  // 开启下拉刷新魔法
        "backgroundTextStyle": "dark",  // 下拉刷新小圆点的样式(light/dark)
        "backgroundColor": "#f8f8f8",  // 下拉刷新背景色
        "backgroundColorTop": "#f4f4f4",  // 下拉刷新顶部背景色(仅APP生效)
        "backgroundColorBottom": "#f4f4f4",  // 下拉刷新底部背景色(仅APP生效)
        "onReachBottomDistance": 50  // 页面上拉触底事件触发时距页面底部距离,单位px
      }
    }
  ]
}

🔮 基础魔法卷轴:简单的下拉刷新实现


export default {
  data() {
    return {
      spellList: ['火球术', '冰冻术', '闪电链', '传送术'],
      lastUpdateTime: '未刷新'
    }
  },
  
  // 监听下拉刷新事件 - 与methods同级
  onPullDownRefresh() {
    console.log('✨ 魔法刷新开始...');
    
    // 模拟获取新数据的过程
    setTimeout(() => {
      // 更新数据
      this.spellList = [
        '高级火球术', 
        '暴风雪', 
        '连锁闪电', 
        '群体传送',
        '时间停止'
      ];
      
      this.lastUpdateTime = new Date().toLocaleTimeString();
      
      // 重要:停止下拉刷新动画
      uni.stopPullDownRefresh();
      
      // 提示用户
      uni.showToast({
        title: '魔法刷新成功!',
        icon: 'success'
      });
      
      console.log('✨ 魔法刷新完成');
    }, 1500); // 1.5秒后完成刷新
  }
}

🧪 实战魔法卷轴:新闻列表刷新


export default {
  data() {
    return {
      newsList: [],
      page: 1,
      isLoading: false
    }
  },
  
  onLoad() {
    // 页面加载时获取第一页数据
    this.fetchNewsList();
  },
  
  // 下拉刷新生命周期
  onPullDownRefresh() {
    console.log('触发下拉刷新');
    
    // 重置到第一页
    this.page = 1;
    
    // 获取最新数据
    this.fetchNewsList(true);
  },
  
  methods: {
    // 获取新闻列表
    fetchNewsList(isPullDown = false) {
      this.isLoading = true;
      
      // 调用新闻API
      uni.request({
        url: `https://your-api.com/news?page=${this.page}`,
        success: (res) => {
          // 如果是下拉刷新,替换现有数据
          if (isPullDown) {
            this.newsList = res.data.list;
            
            // 显示刷新成功提示
            uni.showToast({
              title: '已更新最新内容',
              icon: 'success'
            });
          } else {
            // 否则追加数据
            this.newsList = [...this.newsList, ...res.data.list];
          }
        },
        fail: (err) => {
          uni.showToast({
            title: '刷新失败,请重试',
            icon: 'none'
          });
          console.error('获取新闻失败:', err);
        },
        complete: () => {
          this.isLoading = false;
          
          // 如果是下拉刷新,停止刷新动画
          if (isPullDown) {
            uni.stopPullDownRefresh();
          }
        }
      });
    }
  }
}

🎩 高级魔法卷轴:自定义下拉刷新样式 (App端)


<template>
  <view class="custom-refresh-container">
    <!-- 自定义下拉刷新区域 -->
    <view class="custom-refresh-header" :style="{ height: refreshHeight + 'px' }">
      <view class="refresh-icon" :class="{ 'refreshing': isRefreshing }">
        <image src="/static/refresh-icon.png" mode="aspectFit"></image>
      </view>
      <text class="refresh-text">{{ refreshText }}</text>
    </view>
    
    <!-- 页面内容区域 -->
    <view class="content">
      <view v-for="(item, index) in dataList" :key="index" class="data-item">
        {{ item }}
      </view>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      dataList: ['数据项 1', '数据项 2', '数据项 3', '数据项 4'],
      isRefreshing: false,
      refreshHeight: 0,
      refreshText: '下拉刷新',
      touchStartY: 0
    }
  },
  
  // #ifdef APP-PLUS
  // 在App端使用原生下拉刷新
  onLoad() {
    // 获取当前webview
    const currentWebview = this.$scope.$getAppWebview();
    
    // 设置自定义下拉刷新样式
    currentWebview.setStyle({
      bounce: 'vertical',
      bounceBackground: '#f8f8f8'
    });
    
    // 监听下拉刷新事件
    currentWebview.addEventListener('pulldown', e => {
      this.isRefreshing = true;
      this.refreshText = '正在刷新...';
      
      // 模拟刷新数据
      setTimeout(() => {
        this.dataList = [
          '新数据项 1', 
          '新数据项 2', 
          '新数据项 3', 
          '新数据项 4',
          '新数据项 5'
        ];
        
        this.isRefreshing = false;
        this.refreshText = '刷新成功';
        
        // 停止刷新
        uni.stopPullDownRefresh();
        
        // 延迟恢复初始状态
        setTimeout(() => {
          this.refreshText = '下拉刷新';
        }, 500);
      }, 2000);
    });
  },
  // #endif
  
  // 常规下拉刷新(非App平台)
  // #ifndef APP-PLUS
  onPullDownRefresh() {
    this.isRefreshing = true;
    this.refreshText = '正在刷新...';
    
    setTimeout(() => {
      this.dataList = [
        '新数据项 1', 
        '新数据项 2', 
        '新数据项 3', 
        '新数据项 4',
        '新数据项 5'
      ];
      
      this.isRefreshing = false;
      this.refreshText = '刷新成功';
      
      uni.stopPullDownRefresh();
      
      setTimeout(() => {
        this.refreshText = '下拉刷新';
      }, 500);
    }, 2000);
  },
  // #endif
  
  // 监听触摸事件(自定义下拉效果)
  methods: {
    touchStart(e) {
      this.touchStartY = e.touches[0].clientY;
    },
    
    touchMove(e) {
      const moveY = e.touches[0].clientY;
      const distance = moveY - this.touchStartY;
      
      // 只有向下拉动才处理
      if (distance <= 0) return;
      
      // 设置一个阻尼效果,让下拉不会太夸张
      this.refreshHeight = Math.min(distance * 0.5, 100);
      
      if (this.refreshHeight > 50) {
        this.refreshText = '释放立即刷新';
      } else {
        this.refreshText = '下拉刷新';
      }
    },
    
    touchEnd(e) {
      if (this.refreshHeight > 50) {
        // 触发刷新
        this.isRefreshing = true;
        this.refreshHeight = 60;
        this.refreshText = '正在刷新...';
        
        this.refreshData();
      } else {
        // 取消刷新,恢复初始状态
        this.refreshHeight = 0;
      }
    },
    
    refreshData() {
      setTimeout(() => {
        this.dataList = [
          '新数据项 1', 
          '新数据项 2', 
          '新数据项 3', 
          '新数据项 4',
          '新数据项 5'
        ];
        
        this.isRefreshing = false;
        this.refreshText = '刷新成功';
        
        // 延迟收起刷新区域
        setTimeout(() => {
          this.refreshHeight = 0;
          this.refreshText = '下拉刷新';
        }, 500);
      }, 2000);
    }
  }
}
</script>

<style>
.custom-refresh-container {
  position: relative;
}

.custom-refresh-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background-color: #f0f0f0;
  transition: height 0.2s;
  overflow: hidden;
}

.refresh-icon {
  width: 32px;
  height: 32px;
  margin-bottom: 5px;
}

.refresh-icon image {
  width: 100%;
  height: 100%;
}

.refreshing {
  animation: rotate 1s linear infinite;
}

@keyframes rotate {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.refresh-text {
  font-size: 14px;
  color: #666;
}

.content {
  padding: 15px;
}

.data-item {
  padding: 15px;
  margin-bottom: 10px;
  background-color: #fff;
  border-radius: 8px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
</style>

🔍 下拉刷新的窍门与禁忌

✅ 推荐做法

总是使用
stopPullDownRefresh


onPullDownRefresh() {
  // 数据刷新逻辑...
  
  // 完成后停止刷新动画
  uni.stopPullDownRefresh();
}

处理异步操作


onPullDownRefresh() {
  fetchData().then(res => {
    this.dataList = res.data;
  }).catch(err => {
    console.error(err);
  }).finally(() => {
    // 无论成功失败,都要停止刷新动画
    uni.stopPullDownRefresh();
  });
}

提供视觉反馈


onPullDownRefresh() {
  // 刷新操作...
  
  // 完成后给用户反馈
  uni.showToast({
    title: '刷新成功',
    icon: 'success'
  });
  
  uni.stopPullDownRefresh();
}

❌ 避免的做法

忘记停止刷新动画


// 错误示例
onPullDownRefresh() {
  this.loadData();
  // 忘记调用 uni.stopPullDownRefresh()
}

在刷新过程中重复请求


// 错误示例
onPullDownRefresh() {
  if (this.isRefreshing) return; // 应该添加此类检查
  
  this.isRefreshing = true;
  this.loadData().finally(() => {
    this.isRefreshing = false;
    uni.stopPullDownRefresh();
  });
}

不处理错误情况


// 错误示例
onPullDownRefresh() {
  fetch().then(res => {
    this.data = res;
    uni.stopPullDownRefresh();
  });
  // 没有 catch 错误,如果请求失败,刷新动画会一直显示
}

🧩 下拉刷新与上拉加载的完美组合

想要打造完美的列表体验,下拉刷新通常需要与上拉加载更多配合使用:


export default {
  data() {
    return {
      list: [],
      page: 1,
      hasMore: true,
      isLoading: false
    }
  },
  
  onLoad() {
    this.loadData();
  },
  
  // 下拉刷新
  onPullDownRefresh() {
    // 重置页码
    this.page = 1;
    this.hasMore = true;
    
    // 重新加载第一页
    this.loadData(true);
  },
  
  // 上拉加载更多
  onReachBottom() {
    if (!this.hasMore || this.isLoading) return;
    
    this.page++;
    this.loadData();
  },
  
  methods: {
    loadData(isPullDown = false) {
      if (this.isLoading) return;
      
      this.isLoading = true;
      
      // 显示加载提示
      if (!isPullDown) {
        uni.showLoading({
          title: '加载中...'
        });
      }
      
      // 模拟请求
      setTimeout(() => {
        // 模拟数据
        const newData = Array.from({length: 10}, (_, i) => `第${this.page}页 - 项目${i+1}`);
        
        // 模拟没有更多数据的情况
        if (this.page >= 4) {
          this.hasMore = false;
        }
        
        if (isPullDown) {
          // 下拉刷新,替换数据
          this.list = newData;
        } else {
          // 上拉加载,追加数据
          this.list = [...this.list, ...newData];
        }
        
        this.isLoading = false;
        
        // 隐藏加载提示
        uni.hideLoading();
        
        // 如果是下拉刷新,停止刷新动画
        if (isPullDown) {
          uni.stopPullDownRefresh();
          
          uni.showToast({
            title: '刷新成功',
            icon: 'success'
          });
        }
        
        // 显示是否有更多数据的提示
        if (!this.hasMore) {
          uni.showToast({
            title: '没有更多数据了',
            icon: 'none'
          });
        }
      }, 1000);
    }
  }
}

📱 不同平台的表现差异

不同平台下拉刷新的视觉效果和行为会有所不同:

App:可以高度自定义,支持设置下拉样式和回弹效果H5:效果取决于浏览器实现,相对简单微信小程序:有统一的下拉动画,较难自定义其他小程序:各平台有所差异,但基本功能一致

🎁 总结:下拉刷新的精髓

下拉刷新就像一个简单却强大的魔法咒语,它让你的应用拥有”焕然一新”的能力。记住这些关键点:

配置开启:在pages.json中设置
"enablePullDownRefresh": true

监听刷新:使用
onPullDownRefresh()
生命周期函数捕获下拉事件

结束刷新:务必调用
uni.stopPullDownRefresh()
结束刷新动画

视觉反馈:通过toast或其他方式告知用户刷新结果

错误处理:无论成功失败,都要停止刷新动画

掌握了这些魔法,你的应用将拥有流畅、直观的刷新体验,让用户随时获取最新内容!记住,最好的魔法不是最复杂的,而是最实用的 – 下拉刷新正是如此。

© 版权声明

相关文章

暂无评论

none
暂无评论...