当前位置:首页 > VUE

vue下拉刷新实现案例

2026-02-24 12:37:17VUE

Vue 下拉刷新实现案例

使用第三方库(如 vue-pull-refresh

安装 vue-pull-refresh 库:

npm install vue-pull-refresh --save

在 Vue 组件中引入并使用:

<template>
  <pull-refresh :on-refresh="onRefresh">
    <!-- 你的列表内容 -->
    <ul>
      <li v-for="item in list" :key="item.id">{{ item.text }}</li>
    </ul>
  </pull-refresh>
</template>

<script>
import PullRefresh from 'vue-pull-refresh';

export default {
  components: {
    PullRefresh
  },
  data() {
    return {
      list: [] // 初始数据
    };
  },
  methods: {
    onRefresh() {
      return new Promise((resolve) => {
        setTimeout(() => {
          // 模拟异步加载数据
          this.list = [...this.fetchNewData(), ...this.list];
          resolve();
        }, 1000);
      });
    },
    fetchNewData() {
      // 替换为实际的数据获取逻辑
      return [{ id: Date.now(), text: '新数据' }];
    }
  }
};
</script>

原生实现(基于 Touch 事件)

通过监听触摸事件实现自定义下拉刷新:

<template>
  <div 
    class="pull-refresh"
    @touchstart="handleTouchStart"
    @touchmove="handleTouchMove"
    @touchend="handleTouchEnd"
  >
    <div class="refresh-indicator" :style="{ height: `${pullHeight}px` }">
      {{ refreshText }}
    </div>
    <ul>
      <li v-for="item in list" :key="item.id">{{ item.text }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      list: [],
      startY: 0,
      pullHeight: 0,
      isRefreshing: false,
      maxPullHeight: 80
    };
  },
  computed: {
    refreshText() {
      if (this.isRefreshing) return '加载中...';
      return this.pullHeight >= this.maxPullHeight ? '释放刷新' : '下拉刷新';
    }
  },
  methods: {
    handleTouchStart(e) {
      if (this.isRefreshing) return;
      this.startY = e.touches[0].pageY;
    },
    handleTouchMove(e) {
      if (this.isRefreshing) return;
      const currentY = e.touches[0].pageY;
      const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;

      // 只有在顶部且下拉时才触发
      if (scrollTop === 0 && currentY > this.startY) {
        const distance = currentY - this.startY;
        this.pullHeight = Math.min(distance, this.maxPullHeight);
      }
    },
    handleTouchEnd() {
      if (this.isRefreshing || this.pullHeight < this.maxPullHeight) {
        this.pullHeight = 0;
        return;
      }

      this.isRefreshing = true;
      this.fetchData().finally(() => {
        this.isRefreshing = false;
        this.pullHeight = 0;
      });
    },
    fetchData() {
      return new Promise(resolve => {
        setTimeout(() => {
          this.list = [...this.generateNewData(), ...this.list];
          resolve();
        }, 1500);
      });
    },
    generateNewData() {
      return [{ id: Date.now(), text: '新数据' }];
    }
  }
};
</script>

<style>
.pull-refresh {
  position: relative;
}
.refresh-indicator {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  overflow: hidden;
  color: #666;
}
</style>

使用浏览器原生 API(IntersectionObserver)

结合 IntersectionObserver 实现无感知刷新:

<template>
  <div class="container">
    <ul>
      <li v-for="item in list" :key="item.id">{{ item.text }}</li>
    </ul>
    <div ref="loader" class="loader" v-if="!allLoaded">
      {{ loading ? '加载中...' : '上拉加载更多' }}
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      list: [],
      loading: false,
      allLoaded: false,
      page: 1
    };
  },
  mounted() {
    this.initObserver();
    this.loadData();
  },
  methods: {
    initObserver() {
      const observer = new IntersectionObserver((entries) => {
        if (entries[0].isIntersecting && !this.loading && !this.allLoaded) {
          this.loadData();
        }
      });

      observer.observe(this.$refs.loader);
    },
    loadData() {
      this.loading = true;
      setTimeout(() => {
        const newData = Array(10).fill(0).map((_, i) => ({
          id: this.page * 10 + i,
          text: `项目 ${this.page * 10 + i}`
        }));

        this.list = [...this.list, ...newData];
        this.page++;
        this.loading = false;

        if (this.page > 3) {
          this.allLoaded = true;
        }
      }, 1000);
    }
  }
};
</script>

<style>
.loader {
  padding: 10px;
  text-align: center;
  color: #666;
}
</style>

注意事项

  • 移动端适配需确保 touch 事件正确触发
  • 性能优化:大数据列表应配合虚拟滚动
  • 加载状态需明确反馈给用户
  • 网络错误情况需处理异常状态
  • 原生实现需注意事件冲突(如与滚动条的交互)

vue下拉刷新实现案例

标签: 案例vue
分享给朋友:

相关文章

vue实现轮询

vue实现轮询

实现轮询的基本方法 在Vue中实现轮询可以通过setInterval或setTimeout配合递归调用完成。轮询通常用于定期向服务器请求数据更新。 使用setInterval的简单示例: da…

vue实现triger

vue实现triger

在Vue中实现触发器(trigger)功能通常涉及自定义事件或DOM事件触发。以下是几种常见场景的实现方法: 自定义事件触发 通过$emit方法触发父组件中监听的自定义事件: // 子组件 thi…

vue怎么实现

vue怎么实现

Vue 实现方法 Vue 是一个流行的前端框架,用于构建用户界面。以下是几种常见的实现方法: 数据绑定 使用 v-model 指令实现双向数据绑定,适用于表单输入元素。 <input v-m…

vue实现机制

vue实现机制

Vue 实现机制的核心原理 Vue.js 的核心实现机制主要基于响应式系统、虚拟 DOM 和组件化设计。以下是关键实现细节: 响应式系统 Vue 通过 Object.defineProperty(…

vue实现波形

vue实现波形

实现波形效果的方法 在Vue中实现波形效果可以通过多种方式完成,常见的方法包括使用Canvas绘制、CSS动画或第三方库。以下是几种实现方案: 使用Canvas绘制波形 通过Canvas API动…

vue 实现评分

vue 实现评分

Vue 实现评分功能 在 Vue 中实现评分功能可以通过多种方式完成,包括使用第三方组件库或自定义实现。以下是两种常见的方法: 使用第三方组件库(如 Element UI) Element UI…