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

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

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

下拉刷新


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

下拉加载更多


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

暂无数据


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

以下为代码

scroll.vue文件

template部分


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

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 部分


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

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();

            }

        }

    }

上一篇:InnoDB索引概述,二分查找法,平衡二叉树


下一篇:《Android 源码设计模式解析与实战》——第1章,第1.6节更好的可扩展性——迪米特原则