Vue2.0 实战 之 上拉加载下拉刷新

简介: 目前有很多方式可以实现上拉刷新下拉加载的功能基于vue2.0并参考网上的一些实例完善了一个vue的组件来实现上拉刷新,下拉下载的功能。下拉刷新下拉加载更多暂无数据以下为代码scroll.

目前有很多方式可以实现上拉刷新下拉加载的功能

基于vue2.0并参考网上的一些实例完善了一个vue的组件来实现上拉刷新,下拉下载的功能。

下拉刷新


img_15945fb2a86d1cbf81d43a2782e181be.png

下拉加载更多


img_3e3b946c3f4ba3b65880d727b66417ac.png

暂无数据


img_f4e064b2b56d00deb48581bf2414fffc.png

以下为代码

scroll.vue文件

template部分


img_21fd5f33cba8cf6346390fd74afeb1ee.png

script部分

export default {

  props: {

    offset: {

      type: Number,

      default: 40 // 默认高度

    },

    enableInfinite: {

      type: Boolean,

      default: true

    },

    enableRefresh: {

      type: Boolean,

      default: true

    },

    dataList: {

      default: false,

      required: false

    },

    onRefresh: {

      type: Function,

      default: undefined,

      required: false

    },

    onInfinite: {

      type: Function,

      default: undefined,

      require: false

    }

  },

  data () {

    return {

      top: 0,

      state: 0,

      startX: 0,

      startY: 0,

      touching: false,

      infiniteLoading: false,

      downFlag: true // 用来显示是否加载中

    }

  },

  methods: {

    touchStart (e) {

      this.startY = e.targetTouches[0].pageY

      this.startX = e.targetTouches[0].pageX

      this.startScroll = this.$el.scrollTop || 0

      this.touching = true // 留着有用,不能删除

      this.dataList.noFlag = false

      this.$el.querySelector('.load-more').style.display = 'block'

    },

    touchMove (e) {

      if (!this.enableRefresh || this.dataList.noFlag || !this.touching) {

        return

      }

      let diff = e.targetTouches[0].pageY - this.startY - this.startScroll

      if (diff > 0) e.preventDefault()

      this.top = Math.pow(diff, 0.8) + (this.state === 2 ? this.offset : 0)

      if (this.state === 2) { // in refreshing

        return

      }

      if (this.top >= this.offset) {

        this.state = 1

      } else {

        this.state = 0

      }

      let more = this.$el.querySelector('.load-more')

      if (!this.top && this.state === 0) {

        more.style.display = 'block'

      } else {

        more.style.display = 'none'

      }

    },

    touchEnd (e) {

      if (!this.enableRefresh) {

        return

      }

      this.touching = false

      if (this.state === 2) { // in refreshing

        this.state = 2

        this.top = this.offset

        return

      }

      if (this.top >= this.offset) { // do refresh

        this.refresh()

      } else { // cancel refresh

        this.state = 0

        this.top = 0

      }

      // 用于判断滑动是否在原地 ----begin

      let endX = e.changedTouches[0].pageX

      let endY = e.changedTouches[0].pageY

      let dy = this.startY - endY

      let dx = endX - this.startX

      // 如果滑动距离太短

      if (Math.abs(dx) < 2 && Math.abs(dy) < 2) {

//        console.log('滑动距离太短')

        return

      }

      // --------end--------

      if (!this.enableInfinite || this.infiniteLoading) {

        return

      }

      let outerHeight = this.$el.clientHeight

      let innerHeight = this.$el.querySelector('.inner').clientHeight

      let scrollTop = this.$el.scrollTop

      let ptrHeight = this.onRefresh ? this.$el.querySelector('.pull-refresh').clientHeight : 0

      let bottom = innerHeight - outerHeight - scrollTop - ptrHeight

//      console.log(bottom + '__' + this.offset)

      if (bottom <= this.offset && this.state === 0) {

        this.downFlag = true

        this.infinite()

      } else {

        this.$el.querySelector('.load-more').style.display = 'none'

        this.downFlag = false

      }

    },

    onScroll (e) {

      if (!this.enableInfinite) {

        return

      }

      let outerHeight = this.$el.clientHeight // 屏幕内容区域 316

      let innerHeight = this.$el.querySelector('.inner').clientHeight  // inner height 923

      let scrollTop = this.$el.scrollTop  // 滚动条距顶部高度

      let ptrHeight = this.onRefresh ? this.$el.querySelector('.pull-refresh').clientHeight : 0 // 下拉刷新div高度

      let infiniteHeight = this.$el.querySelector('.load-more').clientHeight // 上拉加载更多div高度

      let bottom = innerHeight - outerHeight - scrollTop - ptrHeight

      if (bottom + infiniteHeight - 1 <= infiniteHeight) {

        this.infinite()

      }

    },

    refresh () {

      this.state = 2

      this.top = this.offset

      setTimeout(() => {

        this.onRefresh(this.refreshDone)

      }, 300)

    },

    refreshDone () {

      this.state = 0

      this.top = 0

    },

    infinite () {

      this.infiniteLoading = true

      setTimeout(() => {

        this.onInfinite(this.infiniteDone)

      }, 2000)

    },

    infiniteDone () {

      this.infiniteLoading = false

    }

  }

}

style部分

.yo-scroll {

    position: absolute;

    top: 2.78rem;

    right: 0;

    bottom: 0;

    left: 0;

    overflow: auto;

    -webkit-overflow-scrolling: touch;

    background-color: #fff

  }

  .yo-scroll .inner {

    position: absolute;

    top: -2rem;

    width: 93%;

    transition-duration: 300ms;

    padding: 0 .25rem;

  }

  .yo-scroll .pull-refresh {

    position: relative;

    left: 0;

    top: 0;

    width: 100%;

    height: 2rem;

    display: flex;

    align-items: center;

    justify-content: center;

    font-size:.3rem;

  }

  .yo-scroll.touch .inner {

    transition-duration: 0ms;

  }

  .yo-scroll.down .down-tip {

    display: block;

  }

  .yo-scroll.up .up-tip {

    display: block;

  }

  .yo-scroll.refresh .refresh-tip {

    display: block;

  }

  .yo-scroll .down-tip,

  .yo-scroll .refresh-tip,

  .yo-scroll .up-tip {

    display: none;

  }

  .yo-scroll .load-more {

    height: 1.5rem;

    text-align: center;

    line-height: 1.5rem;

    display: flex;

    align-items: center;

    justify-content: center;

    font-size:.3rem;

  }

  .nullData{

    font-size: .3rem;

    text-align: center;

    height: 1rem;

    line-height: 1rem;

  }


以下为使用方法

template 部分


img_8d367620c70322b3d4a3337bbc91a9b2.png

script部分

import scroll from '../scroll'

    export default {

        data() {

            return {

                counter: 1, //当前页

                num: 10, // 一页显示多少条

                pageStart: 0, // 开始页数

                pageEnd: 0, // 结束页数

                listdata: [], // 下拉更新数据存放数组

                scrollData: {

                    noFlag: false //暂无更多数据显示

                }

            }

        },

        components: {

            'v-scroll':scroll

        },

        mounted: function() {

            this.getList();

        },

        methods: {

            getList() {

                var response = []

                for(let i = 0; i < 20; i++) {

                    response.push({

                        date: "2017-06-1"+i,

                        portfolio: "1.5195"+i,

                        drop: i+"+.00 %" ,

                        state: 1

                    })

                }

                this.listdata = response.slice(0, this.num);

            },

            onRefresh(done) {

                this.getList();

                done(); // call done

            },

            onInfinite(done) {

                this.counter++;

                let end = this.pageEnd = this.num * this.counter;

                let i = this.pageStart = this.pageEnd - this.num;

                let more = this.$el.querySelector('.load-more')

                for(i; i < end; i++) {

                    if(i >= 30) {

                        more.style.display = 'none'; //隐藏加载条

                        //走完数据调用方法

                        this.scrollData.noFlag = true;

                        break;

                    } else {

                        this.listdata.push({

                            date: "2017-06-1"+i,

                            portfolio: "1.5195"+i,

                            drop: i+"+.00 %" ,

                            state: 2

                        })

                        more.style.display = 'none'; //隐藏加载条

                    }

                }

                done();

            }

        }

    }

相关文章
|
5月前
|
存储 JavaScript 前端开发
前端开发:Vue.js入门与实战
【10月更文挑战第9天】前端开发:Vue.js入门与实战
|
5月前
|
JavaScript 前端开发
Vue开发必备:$nextTick方法的理解与实战场景
Vue开发必备:$nextTick方法的理解与实战场景
393 1
|
4月前
|
JavaScript UED
"Vue实战技巧大揭秘:一招解决路由跳转页面不回顶部难题,让你的单页面应用用户体验飙升!"
【10月更文挑战第23天】在Vue单页面应用中,点击路由跳转时,默认情况下页面不会自动滚动到顶部,这可能影响用户体验。本文通过一个新闻网站的案例,介绍了如何使用Vue-router的全局前置守卫和`scrollBehavior`方法,实现路由跳转时页面自动滚动到顶部的功能,提升用户浏览体验。
181 0
|
6月前
|
JavaScript 前端开发 UED
组件库实战 | 用vue3+ts实现全局Header和列表数据渲染ColumnList
该文章详细介绍了如何使用Vue3结合TypeScript来开发全局Header组件和列表数据渲染组件ColumnList,并提供了从设计到实现的完整步骤指导。
|
7月前
|
JavaScript
Vue学习之--------消息订阅和发布、基础知识和实战应用(2022/8/24)
这篇文章介绍了Vue中消息订阅和发布的机制,作为组件间通信的一种方式,特别适用于任意组件间的通信。文章通过基础知识讲解和具体的代码实例,展示了如何使用`pubsub-js`库来安装、订阅、发布消息,并在组件销毁前取消订阅以避免内存泄漏。
Vue学习之--------消息订阅和发布、基础知识和实战应用(2022/8/24)
|
7月前
|
JavaScript 前端开发 开发者
Vue学习之--------深入理解Vuex、原理详解、实战应用(2022/9/1)
这篇文章详细介绍了Vuex的基本概念、使用场景、安装配置、基本用法、实际应用案例以及注意事项,通过一个数字累加器的实战示例,帮助开发者深入理解Vuex的原理和应用。
|
7月前
|
JavaScript
Vue中组件化编码使用(实战练习一)
这篇文章是关于Vue中组件化编码的实战练习,介绍了组件化编码的流程、组件间参数传递的方法以及如何通过组件配合完成一个需求。内容包括了组件拆分、动态组件实现、交互绑定事件的步骤,以及使用props进行父子组件通信的注意事项。文章还提供了一个待办事项列表的静态页面效果和相关代码示例,包括TheFooter.vue、TheHeader.vue、TheItem.vue、TheList.vue和App.vue等组件的代码。
Vue中组件化编码使用(实战练习一)
|
8月前
|
存储 JavaScript API
Vue 全局状态管理新宠:Pinia实战指南
 随着Vue.js项目的日益复杂,高效的状态管理变得至关重要。Pinia作为Vue.js官方推荐的新一代状态管理库,以其简洁的API和强大的功能脱颖而出。本文将带您快速上手Pinia,从安装到应用,轻松实现Vue.js项目的全局状态管理,提升开发效率和项目可维护性。
|
7月前
|
JavaScript
Vue中组件化编码 完成任务的添加、删除、统计、勾选需求(实战练习三完结)
这篇文章展示了如何在Vue中实现任务添加、删除、勾选和统计功能,通过组件间参数传递和方法实现,提供了App.vue、TheList.vue、TheItem.vue、TheHeader.vue和TheFooter.vue组件的主要代码示例。
|
7月前
|
数据采集 JavaScript
Vue中组件化编码使用、实现组件之间的参数传递(实战练习二)
这篇文章介绍了Vue中组件化编码的实现和组件间参数传递的方法,通过实战练习展示了从App.vue向TheList.vue和TheItem.vue传递数据的流程和代码示例。

热门文章

最新文章