Vue下拉刷新组件

之前写了上拉加载,当然也就有下拉刷新。下拉刷新在web项目中使用会比上拉加载少。这边补充两点:

1、上拉加载和下拉刷新最大意义是说明原理;

2、全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。

下拉刷新原理:

监听touchStart、touchMove、touchEnd,当手指触碰的时候,记录当前位置,然后移动的时候判断,滚动条为0,且移动的距离(当前pageY减去初始触碰的pageY)大于0小于设定的某个值的时候,让加载动画的高度等于移动的距离。移动结束的时候,判断是否大于某个高度,大于就触发刷新方法。

<template>
  <div class="" id="refresh" 
       @touchstart="touchStart($event)" 
       @touchmove="touchMove($event)"
       @touchend="touchEnd($event)">
    <div :style="{'height': loadShowHeight + 'px'}" style="overflow: hidden">
      <slot name="load"></slot>
    </div>
    <slot name="content"></slot>
  </div>
</template>
<script>  
    export default {
      props: ['loadMaxHeight', 'loadMinHeight', 'refresh', 'refreshEnd'],
        data() {
          return {scrollTop: 0, startY: 0, loadShowHeight: 0}
        }, 
        components: {}, mounted() {
          this.scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
        },
        methods: {
          touchStart(e) {
            this.startY = e.targetTouches[0].pageY;
          },
          touchMove(e) {
            if (this.scrollTop == 0) {
              let moveDistance = e.targetTouches[0].pageY - this.startY;
              if (moveDistance > 0 && moveDistance <= (this.loadMaxHeight || 30)) {
                  this.loadShowHeight = moveDistance;
              };
            };
          },
          touchEnd() {
            if (this.loadShowHeight >= (this.loadMinHeight || 20)) {
              this.$emit('refresh', false);
            } else {
              this.loadShowHeight = 0;
            };
          },
        }, 
        watch: {
          refreshEnd(val) {
            if (val) {
              this.loadShowHeight = 0;
            };
          }
        }
    }
</script>
复制代码

使用:

<template>
  <div class="">
    <w-scroll-down loadMaxHeight="80" loadMinHeight="40" @refresh="refresh" :refreshEnd="freshFlag">
      <div slot="load" style="line-height: 30px;color: red"> {{loadMsg}}</div>
      <div slot="content">
        <div style="width: 30px;height: 200px;background: #5fff36"></div>
        <div style="width: 30px;height: 200px;background: #fdff62"></div>
        <div style="width: 30px;height: 200px;background: #ff46a9"></div>
        <div style="width: 30px;height: 200px;background: #ff8938"></div>
        <div style="width: 30px;height: 200px;background: #677eff"></div>
      </div>
    </w-scroll-down>
  </div>
</template>
<script>
    import {wScrollDown} from 'wade-ui'
    export default {
      name: 'HelloWorld',
      data() {
          return {loadMsg: '松开刷新', freshFlag: false}
      },
      methods: {
        refresh(state) {
            this.loadMsg = '刷新中';
            this.freshFlag = state;
            setTimeout(() = > {this.loadMsg = '松开刷新';
            this.freshFlag = true;
        }, 2000);
        }
        },
      components: {wScrollDown}
    }
</script>
复制代码

随便找一个vue项目跑起来就可以看了,这边发现微信发布的时候代码都乱码了,考下来之后格式化一下。

已经部署到npm包:

www.npmjs.com/package/wad…

下载:

Npm install wade-ui -S

欢迎关注Coding个人笔记 公众号

转载于:https://juejin.im/post/5c550027f265da2db66dad43

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下拉刷新是移动 APP 中常见的交互方式,可以提高用户体验,因此我们可以将其封装成一个组件,方便在多个页面中复用。下面是一个简单的 Vue 下拉刷新组件的实现: ```html <template> <div class="pull-refresh-wrapper"> <div class="pull-refresh-status" :class="{'loading': isLoading}"> <div class="pull-refresh-icon"></div> <div class="pull-refresh-text">{{ text }}</div> </div> <div class="pull-refresh-content" ref="content"> <slot></slot> </div> </div> </template> <script> export default { props: { threshold: { type: Number, default: 80 }, text: { type: String, default: '下拉刷新' } }, data() { return { startY: 0, isLoading: false, isDragging: false }; }, mounted() { this.$refs.content.addEventListener('touchstart', this.handleTouchStart); this.$refs.content.addEventListener('touchmove', this.handleTouchMove); this.$refs.content.addEventListener('touchend', this.handleTouchEnd); }, beforeDestroy() { this.$refs.content.removeEventListener('touchstart', this.handleTouchStart); this.$refs.content.removeEventListener('touchmove', this.handleTouchMove); this.$refs.content.removeEventListener('touchend', this.handleTouchEnd); }, methods: { handleTouchStart(e) { this.startY = e.touches[0].clientY; }, handleTouchMove(e) { if (this.isLoading) { return; } const currentY = e.touches[0].clientY; const distance = currentY - this.startY; if (distance > 0 && this.$refs.content.scrollTop === 0) { this.isDragging = true; e.preventDefault(); if (distance >= this.threshold) { this.text = '松开刷新'; } else { this.text = '下拉刷新'; } } else { this.isDragging = false; } }, handleTouchEnd() { if (this.isLoading || !this.isDragging) { return; } if (this.text === '松开刷新') { this.isLoading = true; this.text = '正在刷新'; this.$emit('refresh', () => { this.isLoading = false; this.text = '下拉刷新'; }); } else { this.text = '下拉刷新'; } this.isDragging = false; } } }; </script> <style> .pull-refresh-wrapper { height: 100%; overflow: hidden; } .pull-refresh-status { height: 80px; display: flex; align-items: center; justify-content: center; font-size: 14px; color: #666; } .pull-refresh-icon { width: 16px; height: 16px; margin-right: 8px; border-radius: 50%; border: 2px solid #666; border-top-color: transparent; animation: spin 0.6s linear infinite; } .pull-refresh-text { white-space: nowrap; } .pull-refresh-content { height: calc(100% - 80px); overflow-y: auto; } .loading .pull-refresh-icon { border-color: #42b983; border-top-color: transparent; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } </style> ``` 在上面的代码中,我们使用了 touch 事件来实现下拉刷新。当用户下拉到一定程度时,组件会触发 refresh 事件,我们可以在该事件中进行数据的异步请求。在请求完成后,将 isLoading 设为 false 即可停止 loading 状态。 另外,我们使用了 slot 来插入需要刷新的内容,并监听了 touchstart、touchmove 和 touchend 事件来处理下拉刷新的逻辑。其中,handleTouchMove 方法用于判断下拉距离是否达到阈值,并改变刷新文本的内容;handleTouchEnd 方法用于处理下拉刷新的触发事件,如果下拉距离达到阈值,则触发 refresh 事件,并将 isLoading 设为 true,同时改变刷新文本的内容为“正在刷新”。在事件处理函数中,我们使用了箭头函数来确保 this 指向正确。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值