基于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>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 解决Vue使用mint-ui loadmore实现上拉加载与下拉刷新出现一个页面使用多个上拉加载后冲突问题

    所遇问题: 该页面为双选项卡联动,四个部分都需要上拉加载和下拉刷新功能,使用的mint-ui的loadmore插件,分别加上上拉加载后,只有最后一个的this.$refs.loadmore.onTopLoaded();和this.$refs.loadmore.onBottomLoaded(); 有效,其他的三个都无效,这两句话是意思是查询完要调用一次,用于重新定位 分析原因: 首先这四个模块都是用的 <mt-loadmore :top-method="loadTop" :bott

  • vue移动端下拉刷新和上拉加载的实现代码

    由于自身的项目比较简单,只有几个H5页面,用来嵌入app中,所有没有引入移动端的UI框架,但是介于能让用户在浏览H5页面时有下拉刷新和上拉加载,有更好的用户体验,自己写组件实现. 1.下拉刷新DropDownRefresh.vue <template lang="html"> <div class="refreshMoudle" @touchstart="touchStart($event)" @touchmove="

  • vue.js整合vux中的上拉加载下拉刷新实例教程

    前言 Vux 是基于 Vue 和 Weui 开发的手机端页面 UI 组件库,开发初衷是满足公司的微信端表单需求,因为第三方的调查问卷表单系统在手机上实在比较丑(还是 PC 那一套样式适配了大小而已).于是用 vue 重构了表单组件,后来一发不可收拾把其他常用组件也一并开发了. 相比于 React 还是更喜欢用 Vue ,除了目前社区组件不多,周边构建工具还是比较完善的(作者也特别勤奋). 下面话不多说了,来一看看详细的介绍吧. 先上图 创建项目 使用vue-cli 创建一个vue项目 安装vux

  • vue.js移动端app之上拉加载以及下拉刷新实战

    上拉加载以及下拉刷新都是移动端很常见的功能,在搜索或者一些分类列表页面常常会用到. 跟横向滚动一样,我们还是采用better-scroll这个库来实现.由于better已经更新了新的版本,之前是0.几的版本,更新了一下发现,现在已经是1.2.6这个版本了,新版本多了些 比较好用的api,所以我也重写了之前的代码,用新的api来实现上拉加载以及下拉刷新. 首先把基本的样式写好,这里就略过了,然后引入better-scroll库 import BScroll from 'better-scroll'

  • vue2.0 移动端实现下拉刷新和上拉加载更多的示例

    本人正在基于 vue2.0 + webpack + es6 搭建前端架构,整理了部分插件,下面这个是下拉更新 上拉更多的,挺好用的,分享给大家. 直接上代码,不懂的多看几遍,下面我换会告诉大家如何使用. <template lang="html"> <div class="yo-scroll" :class="{'down':(state===0),'up':(state==1),refresh:(state===2),touch:tou

  • vue使用better-scroll实现下拉刷新、上拉加载

    本文目的是为了实现列表的下拉刷新.上拉加载,所以选择了better-scroll这个库. 用好这个库,需要理解下面说明 必须包含两个大的div,外层和内层div 外层div设置可视的大小(宽或者高)-有限制宽或高 内层div,包裹整个可以滚动的部分 内层div高度一定大于外层div的宽或高,才能滚动 1.先开始写一个简单demo,最基本的代码架构 template <div ref="wrapper" class="wrapper"> <ul cl

  • vue mintui-Loadmore结合实现下拉刷新和上拉加载示例

    mintui是饿了么团队针对vue开发的移动端组件库,方便实现移动端的一些功能,这里只用了Loadmore功能实现移动端的上拉分页刷新,下拉加载数据,废话不说上代码. <template> <div class="main-body" :style="{'-webkit-overflow-scrolling': scrollMode}"> <v-loadmore :top-method="loadTop" :bott

  • vueScroll实现移动端下拉刷新、上拉加载

    移动端开发,处理列表翻页和数据的时候,下拉刷新和上拉加载应用的比较广泛,今天给大家推荐一个vue的插件,vueScroll,首先上图: 话不多说,上代码了: 一.引入并使用VueScroll import VueScroller from 'vue-scroller'; Vue.use(VueScroller) 二.在html或者.vue组件里面使用 三.在js文件里面操作插件 首先在在methods里面写上方法 在data里面实现申明好 isLoading = true; 然后继续在metho

  • vue插件mescroll.js实现移动端上拉加载和下拉刷新

    做一个简单的移动端展示项目,后台分页后前端加载,实现上拉加载下一页,找了下,还是用这个mescroll.js插件好一点 1.npm安装 npm install --save mescroll.js //不要使用cnpm安装 导入(在哪个页面使用,则在哪个页面导入(这里的话,我使用全局导入会出现问题,若有错,还请大家指出,暂时想到的就是局部引入)): import MescrollVue from 'mescroll.js/mescroll.vue' 注册组件: components: { Mes

  • vue实现网络图片瀑布流 + 下拉刷新 + 上拉加载更多(步骤详解)

    一.思路分析和效果图 用vue来实现一个瀑布流效果,加载网络图片,同时有下拉刷新和上拉加载更多功能效果.然后针对这几个效果的实现,捋下思路: 根据加载数据的顺序,依次追加标签展示效果: 选择哪种方式实现瀑布流,这里选择绝对定位方式: 关键问题:由于每张图片的宽高不一样,而瀑布流中要求所有图片的宽度一致,高度随宽度等比缩放.而且由于图片的加载是异步延迟.在不知道图片高度的情况下,每个图片所在的item盒子不好绝对定位.因此在渲染页面前先获取所有图片的高度,是解决问题的关键点!这里选择用JS中的Im

随机推荐