首页 > 编程 > JavaScript > 正文

基于vue2实现上拉加载功能

2019-11-19 14:50:54
字体:
来源:转载
供稿:网友

本文实例为大家分享了vue2实现上拉加载展示的具体代码,供大家参考,具体内容如下

因为我们项目中,还用了swiper。很多都是滑动切换的,但是又得上拉加载,所以导致,很多UI框架,我们用了,都有不同的bug出现,没办法,最后写了一个。代码如下(这个因为很多地方会用,所以建议放在components/common下面):

<template>  <div class="loadmore">    <slot></slot>    <slot name="bottom">    </slot>  </div></template><style>  .loadmore{    width:100%;  }</style><script>  export default {    name: 'loadmore',    props: {      maxDistance: {        type: Number,        default: 0      },      autoFill: {        type: Boolean,        default: true      },      distanceIndex: {        type: Number,        default: 2      },      bottomPullText: {        type: String,        default: '上拉刷新'      },      bottomDropText: {        type: String,        default: '释放更新'      },      bottomLoadingText: {        type: String,        default: '加载中...'      },      bottomDistance: {        type: Number,        default: 70      },      bottomMethod: {        type: Function      },      bottomAllLoaded: {        type: Boolean,        default: false      },    },    data() {      return {        // 最下面出现的div的位移        translate: 0,        // 选择滚动事件的监听对象        scrollEventTarget: null,        containerFilled: false,        bottomText: '',        // class类名        bottomDropped: false,        // 获取监听滚动元素的scrollTop        bottomReached: false,        // 滑动的方向  down---向下互动;up---向上滑动        direction: '',        startY: 0,        startScrollTop: 0,        // 实时的clientY位置        currentY: 0,        topStatus: '',        // 上拉加载的状态  ''   pull: 上拉中        bottomStatus: '',      };    },    watch: {      // 改变当前加载在状态      bottomStatus(val) {        this.$emit('bottom-status-change', val);        switch (val) {          case 'pull':            this.bottomText = this.bottomPullText;            break;          case 'drop':            this.bottomText = this.bottomDropText;            break;          case 'loading':            this.bottomText = this.bottomLoadingText;            break;        }      }    },    methods: {      onBottomLoaded() {        this.bottomStatus = 'pull';        this.bottomDropped = false;        this.$nextTick(() => {          if (this.scrollEventTarget === window) {          document.body.scrollTop += 50;        } else {          this.scrollEventTarget.scrollTop += 50;        }        this.translate = 0;      });        // 注释        if (!this.bottomAllLoaded && !this.containerFilled) {          this.fillContainer();        }      },      getScrollEventTarget(element) {        let currentNode = element;        while (currentNode && currentNode.tagName !== 'HTML' &&        currentNode.tagName !== 'BODY' && currentNode.nodeType === 1) {          let overflowY = document.defaultView.getComputedStyle(currentNode).overflowY;          if (overflowY === 'scroll' || overflowY === 'auto') {            return currentNode;          }          currentNode = currentNode.parentNode;        }        return window;      },      // 获取scrollTop      getScrollTop(element) {        if (element === window) {          return Math.max(window.pageYOffset || 0, document.documentElement.scrollTop);        } else {          return element.scrollTop;        }      },      bindTouchEvents() {        this.$el.addEventListener('touchstart', this.handleTouchStart);        this.$el.addEventListener('touchmove', this.handleTouchMove);        this.$el.addEventListener('touchend', this.handleTouchEnd);      },      init() {        this.bottomStatus = 'pull';        // 选择滚动事件的监听对象        this.scrollEventTarget = this.getScrollEventTarget(this.$el);        if (typeof this.bottomMethod === 'function') {          // autoFill 属性的实现  注释          this.fillContainer();          // 绑定滑动事件          this.bindTouchEvents();        }      },      // autoFill 属性的实现  注释      fillContainer() {        if (this.autoFill) {          this.$nextTick(() => {            if (this.scrollEventTarget === window) {            this.containerFilled = this.$el.getBoundingClientRect().bottom >=                document.documentElement.getBoundingClientRect().bottom;          } else {            this.containerFilled = this.$el.getBoundingClientRect().bottom >=                this.scrollEventTarget.getBoundingClientRect().bottom;          }          if (!this.containerFilled) {            this.bottomStatus = 'loading';            this.bottomMethod();          }        });        }      },      // 获取监听滚动元素的scrollTop      checkBottomReached() {        if (this.scrollEventTarget === window) {          return document.body.scrollTop + document.documentElement.clientHeight >= document.body.scrollHeight;        } else {          // getBoundingClientRect用于获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置。 right是指元素右边界距窗口最左边的距离,bottom是指元素下边界距窗口最上面的距离。          return this.$el.getBoundingClientRect().bottom <= this.scrollEventTarget.getBoundingClientRect().bottom + 1;        }      },      // ontouchstart 事件      handleTouchStart(event) {        // 获取起点的y坐标        this.startY = event.touches[0].clientY;        this.startScrollTop = this.getScrollTop(this.scrollEventTarget);        this.bottomReached = false;        if (this.bottomStatus !== 'loading') {          this.bottomStatus = 'pull';          this.bottomDropped = false;        }      },      // ontouchmove事件      handleTouchMove(event) {        if (this.startY < this.$el.getBoundingClientRect().top && this.startY > this.$el.getBoundingClientRect().bottom) {          // 没有在需要滚动的范围内滚动,不再监听scroll          return;        }        // 实时的clientY位置        this.currentY = event.touches[0].clientY;        // distance 移动位置和开始位置的差值    distanceIndex---        let distance = (this.currentY - this.startY) / this.distanceIndex;        // 根据 distance 判断滑动的方向 并赋予变量  direction down---向下互动;up---向上滑动        this.direction = distance > 0 ? 'down' : 'up';        if (this.direction === 'up') {          // 获取监听滚动元素的scrollTop          this.bottomReached = this.bottomReached || this.checkBottomReached();        }        if (typeof this.bottomMethod === 'function' && this.direction === 'up' &&            this.bottomReached && this.bottomStatus !== 'loading' && !this.bottomAllLoaded) {          // 有加载函数,是向上拉,有滚动距离,不是正在加载ajax,没有加载到最后一页          event.preventDefault();          event.stopPropagation();          if (this.maxDistance > 0) {            this.translate = Math.abs(distance) <= this.maxDistance                ? this.getScrollTop(this.scrollEventTarget) - this.startScrollTop + distance : this.translate;          } else {            this.translate = this.getScrollTop(this.scrollEventTarget) - this.startScrollTop + distance;          }          if (this.translate > 0) {            this.translate = 0;          }          this.bottomStatus = -this.translate >= this.bottomDistance ? 'drop' : 'pull';        }      },      // ontouchend事件      handleTouchEnd() {        if (this.direction === 'up' && this.bottomReached && this.translate < 0) {          this.bottomDropped = true;          this.bottomReached = false;          if (this.bottomStatus === 'drop') {            this.translate = '-50';            this.bottomStatus = 'loading';            this.bottomMethod();          } else {            this.translate = '0';            this.bottomStatus = 'pull';          }        }        this.direction = '';      }    },    mounted() {      this.init();    }  };</script>

然后哪个页面需要,在哪个页面导入即可:import LoadMore from './../common/loadmore.vue';在需要引入他的页面写法如下:

<template> <section class="finan">  <!-- 上拉加载更多 -->  <load-more  :bottom-method="loadBottom"  :bottom-all-loaded="allLoaded"  :bottomPullText='bottomText'  :auto-fill="false"  @bottom-status-change="handleBottomChange"  ref="loadmore">    <div>  这里写你需要的另外的模块    </div>    <div v-show="loading" slot="bottom" class="loading"> 这个div是为让上拉加载的时候显示一张加载的gif图     <img src="./../../assets/main/uploading.gif">    </div>  </load-more> </section></template>

然后在此页面的data里和methods设置如下:

  export default {    name: 'FinancialGroup',    props:{     },    data () {      return {        // 上拉加载数据        scrollHeight: 0,        scrollTop: 0,        containerHeight: 0,        loading: false,        allLoaded: false,        bottomText: '上拉加载更多...',        bottomStatus: '',        pageNo: 1,        totalCount: '',      }    },    methods: {    /* 下拉加载 */    _scroll: function(ev) {      ev = ev || event;      this.scrollHeight = this.$refs.innerScroll.scrollHeight;      this.scrollTop = this.$refs.innerScroll.scrollTop;      this.containerHeight = this.$refs.innerScroll.offsetHeight;    },    loadBottom: function() {      this.loading = true;      this.pageNo += 1;  // 每次更迭加载的页数      if (this.pageNo == this.totalGetCount) {        // 当allLoaded = true时上拉加载停止        this.loading = false;        this.allLoaded = true;      }      api.commonApi(后台接口,请求参数) 这个api是封装的axios有不懂的可以看vue2+vuex+axios那篇文章          .then(res => {        setTimeout(() => {      要使用的后台返回的数据写在setTimeout里面         this.$nextTick(() => {          this.loading = false;        })      }, 1000)     });    },    handleBottomChange(status) {      this.bottomStatus = status;    },  }

这样就完成了。

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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表