vue组件封装之下拉刷新上拉加载(原生)

基于vue和原生javascript封装的下拉刷新上拉加载组件

  • upTilte插槽是下拉刷新的自定义内容放的地方
  • downTilte插槽是上拉加载的自定义内容放的地方
  • 默认插槽为列表内容区域
  • 组件代码如下
<template>
  <div class="refresh" id="refresh">
    <slot name="upTilte"></slot>
    <slot></slot>
    <slot name="downTilte"></slot>
  </div>
</template>

<script>
export default {
  name: 'PullupOrPulldownRefresh',
  props: {
    // 最大移动距离
    maxMove: {
      type: Number,
      default: 300
    },
    // 阻尼系数
    friction: {
      type: Number,
      default: 0.3
    }
  },
  data() {
    return {
      startY: 0,
      ul: null,
      draw: null,
      up: null,
      down: null,
      y: 0 // 惯性回弹的距离
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.draw = document.getElementById('refresh')
      this.ul = this.draw.children[1]
      this.up = this.draw.children[0]
      this.down = this.draw.children[2]
      this.draw.addEventListener('touchstart', this.touchstart)
      this.draw.addEventListener('touchmove', this.touchmoveEvent)
      this.draw.addEventListener('touchend', this.touchendEvent)
    })
  },
  methods: {
    // 触摸开始事件
    touchstart(event) {
      this.startY = event.changedTouches[0].clientY
    },
    // 触摸移动事件
    touchmoveEvent(event) {
      const height = this.ul.clientHeight - this.draw.clientHeight
      if (height === this.draw.scrollTop || this.draw.scrollTop === 0) {
        var a = event.changedTouches[0].clientY - this.startY
        this.y = a <= this.maxMove ? a : this.maxMove
        // 为了清除卡顿问题,需要清除过渡效果
        this.ul.style.transition = 'none'
        this.ul.style.transform = 'translateY(' + this.friction * this.y + 'px)'
        // 修改状态
        const upHeight = -this.up.clientHeight + this.friction * this.y
        // 下拉开始
        if (this.friction * this.y > 0) (this.setStatus(this.friction * this.y), this.up.style.transition = 'none', this.up.style.transform = 'translateY(' + upHeight + 'px) translateX(-50%)')
        // 上拉开始
        if (this.friction * this.y < 0) (this.setStatus(this.friction * this.y), this.down.style.transition = 'none', this.down.style.marginTop = this.friction * this.y + 'px')
      }
    },
    // 触摸结束事件
    touchendEvent(event) {
      if (this.friction * this.y >= 50) this.$emit('RefreshUp', this.friction * this.y)
      else if (this.friction * this.y < -50) this.$emit('RefreshDown', this.friction * this.y)
      else this.resetStyle()
    },
    // 重置并且添加过渡效果
    resetStyle() {
      this.ul.style.transition = 'transform .6s'
      this.ul.style.transform = 'translateY(' + 0 + 'px)'
      this.up.style.transition = 'all .6s'
      this.up.style.transform = 'translateY(-' + this.up.clientHeight + 'px) translateX(-50%)'
      this.down.style.transition = 'all .6s'
      this.down.style.marginTop = -this.down.clientHeight + 'px'
    },
    // 设置刷新状态
    setStatus(y) {
      this.$emit('setStatus', y)
    }
  }
}
</script>

<style lang="scss">
.refresh {
  width: 100%;
  height: 100vh;
  border: 2px solid #ccc;
  position: relative;
  overflow: hidden;
  overflow: auto;
  position: fixed;
  ul {
    zoom: 1;
    padding: 0 10%;
  }

  ul::after {
    content: '';
    display: block;
    visibility: hidden;
    height: 0;
    clear: both;
  }

  li {
    list-style: none;
    width: 100%;
    height: 50px;
    line-height: 50px;
    text-align: center;
  }
  .UpRefresh {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    z-index: -9;
  }
  .DownRefresh {
    position: relative;
    left: 50%;
    transform: translateX(-50%);
    margin-top: -10px;
    z-index: -9;
  }
}
</style>
  • 组件的使用方法
  • friction为摩擦系数
  • @RefreshUp为下拉到一定距离触发事件
  • @RefreshDown为上拉到一定距离触发事件
  • @setStatus为更改刷新状态的方法
<template>
  <div>
    <PullupOrPulldownRefresh
      ref="PullupOrPulldownRefresh"
      :maxMove="maxMove"
      :friction="friction"
      @RefreshUp="RefreshUp"
      @RefreshDown="RefreshDown"
      @setStatus="setStatus"
    >
      <template v-slot:upTilte>
        <!-- <div class="UpRefresh" v-show="isUpRefresh">{{ Uptitle }}</div> -->
        <div class="UpRefresh" v-show="isUpRefresh">
          <img :src="require('@/assets/logo.png')" alt="" />
          <p>{{ Uptitle }}</p>
        </div>
      </template>
      <ul>
        <li
          v-for="(item, index) in data"
          :key="index"
          style="background: orange"
        >
          {{ item }}
        </li>
      </ul>
      <template v-slot:downTilte>
        <div class="DownRefresh" v-show="isDownRefresh">{{ Downtitle }}</div>
      </template>
    </PullupOrPulldownRefresh>
  </div>
</template>

<script>
export default {
  data() {
    return {
      maxMove: 300,
      friction: 0.3,
      data: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
      isUpRefresh: false,
      isDownRefresh: false,
      Downtitle: '上拉加载更多',
      Uptitle: '下拉刷新'
    }
  },
  methods: {
    setStatus(y) {
      if (y && y > 0) {
        this.isUpRefresh = true
        this.Uptitle = '下拉刷新'
        if (y >= 50) this.Uptitle = '松手刷新'
        return
      }
      this.isDownRefresh = true
      this.Downtitle = '上拉加载更多'
      if (y <= -50) this.Downtitle = '松手加载更多'
    },
    RefreshUp(y) {
      if (!y) return
      if (y >= 50) {
        this.Uptitle = '正在刷新'
        setTimeout(() => {
          for (var i = 1; i <= 10; i++) {
            this.data.push(this.data[this.data.length - 1] + 1)
          }
          this.$refs.PullupOrPulldownRefresh.resetStyle() // 回弹重置
        }, 1000)
      }
    },
    RefreshDown(y) {
      if (!y) return
      if (y <= -50) {
        this.Downtitle = '正在加载'
        setTimeout(() => {
          for (var i = 1; i <= 10; i++) {
            this.data.push(this.data[this.data.length - 1] + 1)
          }
          this.$refs.PullupOrPulldownRefresh.resetStyle() // 回弹重置
        }, 1000)
      }
    }
  }
}
</script>

<style scoped lang="scss">
.UpRefresh img{
  width: 30px;
}
</style>
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
上拉加载下拉刷新组件是一种在Vue中实现页面数据的动态加载和刷新的组件。它可以通过监听用户的上拉下拉动作,触发相应的方法来更新页面数据。根据提供的引用内容,有两种方法可以实现该组件。 方法一:使用父组件调用的方法 在父组件的template块中,使用<wv-pull-refresh>标签包裹需要刷新的内容,然后在script块中导入组件并定义refresh方法,该方法会在下拉刷新时被调用,并在500ms后将子组件的状态归零。 ```javascript <template> <wv-pull-refresh @refresh="refresh"> <div> //页面内容...... </div> </wv-pull-refresh> </template> <script> import wvPullRefresh from "../../ui/wvPullRefresh" export default { components: { wvPullRefresh }, methods: { refresh(done) { setTimeout(() => { done() //把子组件的状态归0 }, 500) } } } </script> <style scoped lang="less"> // ... </style> ``` 方法二:使用工具类的方法 在组件的template块中,同样使用<wv-pull-refresh>标签包裹需要刷新的内容,然后在script块中导入工具类并定义refresh方法。在created生命周期钩子中监听scroll事件,并使用函数节流的思路限制方法的执行频率,防止滚动过程中方法被频繁调用。在setTimer方法中使用getMoreOfScroll方法判断是否滚动到底部,如果是则调用getDataList方法来获取数据,并在500ms后将子组件的状态归零。 ```javascript <template> <wv-pull-refresh @refresh="refresh"> <div> //页面内容...... </div> </wv-pull-refresh> </template> <script> import tools from '../../lib/tools' import wvPullRefresh from "../../ui/wvPullRefresh" export default { components: { wvPullRefresh }, data () { return { valid: true } }, created() { //监听scroll事件 window.addEventListener('scroll', this.setTimer); }, methods: { //因为工具类中方法滚动条还没到达底部就开始执行,向下滚动过程中方法会执行很多次 //这里使用函数节流的思路给限制一下防止频繁调用 setTimer() { if (!this.valid) { return false } this.valid = false setTimeout(() => { this.getMore() this.valid = true; }, 500) }, getMore() { return tools.getMoreOfScroll(this.getDataList) }, getDataList() { //ajax请求方法 }, refresh(done) { setTimeout(() => { done() //把子组件的状态归0 }, 500) } } } </script> <style scoped lang="less"> // ... </style> ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值