当前位置:首页 > 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 实现无感知刷新:

vue下拉刷新实现案例

<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.js 是一个渐进式 JavaScript 框架,其核心逻辑围绕数据驱动和组件化开发。通过响应式系统、虚拟 DOM 和组件生命周期等机制,Vue 实现了高效的前端开发…

vue 实现全屏

vue 实现全屏

Vue 实现全屏功能 在 Vue 中实现全屏功能可以通过浏览器提供的 Fullscreen API 完成。以下是一个完整的实现方案: 安装依赖(可选) 如果需要跨浏览器兼容性更好,可以安装…

vue实现tree

vue实现tree

Vue 实现 Tree 组件 使用 Vue 实现 Tree 组件可以通过递归组件的方式来实现层级结构展示。以下是一个完整的实现方法: 基础递归组件实现 创建 Tree 组件文件 Tree.vue,使…

vue实现心电图

vue实现心电图

Vue 实现心电图效果 在 Vue 中实现心电图效果通常需要结合 Canvas 或 SVG 进行动态绘图,模拟心电图数据的实时变化。以下是两种实现方式的核心思路和代码示例: 使用 Canvas 绘制…

vue filter 实现

vue filter 实现

在 Vue.js 中,过滤器(Filter)是一种用于文本格式化的功能,可以在模板中直接使用。以下是实现过滤器的详细方法: 全局过滤器注册 通过 Vue.filter 方法注册全局过滤器,可在所有组…

vue 实现跳转

vue 实现跳转

Vue 实现页面跳转的方法 在 Vue 中实现页面跳转通常可以通过以下几种方式实现,具体选择取决于项目需求和技术栈(如是否使用 Vue Router)。 使用 Vue Router 进行编程式导航…