better-scroll在vue的使用

某一個(gè)頁(yè)面的列表使用better-scroll的上拉加載和下拉刷新功能,better-scroll被封裝成vue的組件

1。頁(yè)面中

 <my-scroll
        ref="myScroll"
        :startY="parseInt(startY)"
        :listArr="state.testList"  // 列表數(shù)據(jù)
        :haveDataFlag="state.listHaveDataFlag" //分頁(yè)請(qǐng)求,下一頁(yè)是否有數(shù)據(jù)的標(biāo)識(shí)
        :pullup="pullupFlag" // 是否開(kāi)啟上拉加載
        @scrollEnd="onLoadFun" // 上拉加載的方法
        :pullDownRefresh="pullDownRefreshObj" // 是否派發(fā)下拉刷新
        @pullingDown="onPullingDown" //下拉刷新的方法
      >
        <test-list></test-list> //列表
      </my-scroll>

data() {
    return {
      pullDownRefresh: true,
      startY: 0,
      pullDownRefreshThreshold: 90, 
      pullDownRefreshStop: 40,
      pullupFlag: true, // 上拉加載
    };
  },

computed:{
  pullDownRefreshObj() {
      return this.pullDownRefresh
        ? {
            threshold: parseInt(this.pullDownRefreshThreshold),
            stop: parseInt(this.pullDownRefreshStop)
          }
        : false;
    }
}
methods:{
    // 上拉加載
    async onLoadFun() {
      await this.updateInfo({
        pageNum: this.state.pageNum+ 1
      });
      if (this.state.nextTestList.length === 0) {
// 如果下一頁(yè)沒(méi)有數(shù)據(jù),停止上拉加載
        this.pullupFlag = false;
        return;
      }
// 請(qǐng)求接口
      await this.listRequest();
    },
    // 下拉刷新
    async onPullingDown() {
    //打印this可以看到_isDestroyed,當(dāng)前實(shí)例是否已經(jīng)被銷毀
      if (this._isDestroyed) return;
      await this.updateInfo({
        stockMarketPageNum: 1, // 行情列表分頁(yè)
        stockMarketList: [], // 行情列表
        nextStockMarketList: [] //行情新請(qǐng)求列表
      });
      this.listRequest();
    },
// 重新初始化組件
rebuildScroll() {
      Vue.nextTick(() => {
        this.$refs.myScroll.destroy();
        this.$refs.myScroll.initScroll();
      });
    },
},
 watch: {
    startY(nval,oval) {
      this.rebuildScroll();
    }
  },

  1. 組件中
<template>
  <div class="my-scroll" ref="myScroll">
    <div class="scroll-content">
      <slot></slot>
      <div class="pull-up-box" v-if="fatherNeedPullFlag">
        <img
          v-show="isPullUp"
          src="@/assets/img/loading_01.gif"
          alt
          style="width:0.2rem;height0.2rem;"
        />
        <div :class="listArr.length > 0 ? 'have-data':'no-data'">
          <span v-show="haveDataFlag">沒(méi)有更多數(shù)據(jù)了</span>
        </div>
      </div>
    </div>
    <slot
      name="pulldown"
      :pullDownRefresh="pullDownRefresh"
      :pullDownStyle="pullDownStyle"
      :beforePullDown="beforePullDown"
      :isPullingDown="isPullingDown"
    >
      <div ref="pulldown" class="pulldown-wrapper" :style="pullDownStyle" v-if="pullDownRefresh">
        <div class="before-trigger" v-if="beforePullDown"></div>
        <div class="after-trigger" v-else>
          <div v-if="isPullingDown" class="loading">
            <img style="width:0.3rem;height:0.3rem;" src="@/assets/img/loading_01.gif" />
          </div>
          <div v-else>
            <p class="refresh-txt">{{ refreshTxt }}</p>
          </div>
        </div>
      </div>
    </slot>
  </div>
</template>

<script type="text/ecmascript-6">
import BScroll from "better-scroll";
export default {
  name: "myScroll",
  data() {
    return {
      beforePullDown: true,
      pullDownStyle: "",
      isPullingDown: false,
      isRebounding: false
    };
  },
  props: {
    scrollFun: {
      type: Function,
      default: function() {
        return f => f;
      }
    },
    /**
     * 1 滾動(dòng)的時(shí)候會(huì)派發(fā)scroll事件,會(huì)截流。
     * 2 滾動(dòng)的時(shí)候?qū)崟r(shí)派發(fā)scroll事件,不會(huì)截流。
     * 3 除了實(shí)時(shí)派發(fā)scroll事件,在慣性或動(dòng)畫的情況下仍然能實(shí)時(shí)派發(fā)scroll事件
     */
    probeType: {
      type: Number,
      default: 1
    },
    /**
     * 點(diǎn)擊列表是否派發(fā)click事件
     */
    click: {
      type: Boolean,
      default: true
    },
    /**
     * 是否開(kāi)啟橫向滾動(dòng)
     */
    scrollX: {
      type: Boolean,
      default: false
    },
    /**
     * 是否派發(fā)滾動(dòng)事件
     */
    listenScroll: {
      type: Boolean,
      default: false
    },
    /**
     * 列表的數(shù)據(jù)
     */
    listArr: {
      type: Array,
      default: null
    },
    /**
     * 是否派發(fā)滾動(dòng)到底部的事件,用于上拉加載
     */
    pullup: {
      type: Boolean,
      default: false
    },
    /**
     * 是否派發(fā)頂部下拉的事件,用于下拉刷新
     */
    pullDownRefresh: {
      type: null,
      default: false
    },
    /**
     * 是否派發(fā)列表滾動(dòng)開(kāi)始的事件
     */
    beforeScroll: {
      type: Boolean,
      default: false
    },
    /**
     * 當(dāng)數(shù)據(jù)更新后,刷新scroll的延時(shí)。
     */
    refreshDelay: {
      type: Number,
      default: 20
    },
    bounce: {
      // 當(dāng)滾動(dòng)超過(guò)邊緣的時(shí)候會(huì)有一小段回彈動(dòng)畫
      type: Boolean,
      default: true
    },
    fatherNeedPullFlag: {
      // 是否展示底部加載動(dòng)畫和文字
      type: Boolean,
      default: true
    },
    // nextListArr: { // 下次請(qǐng)求的新數(shù)據(jù)
    //   type:Array,
    //   default:[]
    // },
    isPullUp: {
      type: Boolean,
      default: false
    },
    haveDataFlag: {
      type: Boolean,
      default: false
    }
  },
  created() {
    this.pullDownInitTop = -40;
  },
  computed: {
    refreshTxt() {
      return (this.pullDownRefresh && this.pullDownRefresh.txt) || "刷新成功";
    }
  },
  mounted() {
    this.$nextTick(() => {
      this._initScroll();
    });
  },
  destroyed() {
    this.$refs.myScroll && this.$refs.myScroll.destroy();
  },
  methods: {
    _initScroll() {
      if (!this.$refs.myScroll) {
        return;
      }
      let options = {
        probeType: this.probeType,
        scrollX: this.scrollX,
        bounce: this.bounce, // 回彈動(dòng)畫
        pullup: this.pullup,
        pullDownRefresh: this.pullDownRefresh,
        taps: true,
        click: true
      };
      // better-scroll的初始化
      this.scroll = new BScroll(this.$refs.myScroll, options);
      // 是否派發(fā)滾動(dòng)事件
      if (this.listenScroll) {
        this.scroll.on("scroll", pos => {
          this.$emit("scroll", pos);
        });
      }
      // 是否派發(fā)滾動(dòng)到底部事件,用于上拉加載
      if (this.pullup) {
        this.scroll.on("scrollEnd", () => {
          // 滾動(dòng)到底部
          if (this.scroll.y <= this.scroll.maxScrollY + 50) {
            this.$emit("scrollEnd");
          }
        });
      }
      // 監(jiān)聽(tīng)滾動(dòng)高度
      if (this.scrollFun) {
        this.scroll.on("scroll", scrollValue => {
          // 滾動(dòng)到底部
          // console.log(scrollValue.y)
          this.$emit("scrollFun", scrollValue);
        });
      }

      // 是否派發(fā)頂部下拉事件,用于下拉刷新
      if (this.pullDownRefresh) {
        this._initPullDownRefresh();
      }
      // 是否派發(fā)列表滾動(dòng)開(kāi)始的事件
      if (this.beforeScroll) {
        this.scroll.on("beforeScrollStart", () => {
          this.$emit("beforeScroll");
        });
      }
    },
    forceUpdate() {
      if (this.pullDownRefresh && this.isPullingDown) {
        this.isPullingDown = false;
        this._reboundPullDown().then(() => {
          this._afterPullDown();
        });
      }
      if (this.pullup && this.isPullUp) {
        this.isPullUp = false;
        this.scroll.finishPullUp();
        this.refresh();
      } else {
        this.refresh();
      }
    },
    _afterPullDown() {
      setTimeout(() => {
        this.pullDownStyle = `top:${this.pullDownInitTop}px`;
        this.beforePullDown = true;
        this.isRebounding = false;
        this.refresh();
      }, this.scroll.options.bounceTime);
    },
    _initPullDownRefresh() {
      this.scroll.on("pullingDown", () => {
        this.beforePullDown = false;
        this.isPullingDown = true;
        this.$emit("pullingDown");
      });

      this.scroll.on("scroll", pos => {
        if (!this.pullDownRefresh) {
          return;
        }
        if (this.beforePullDown) {
          this.pullDownStyle = `top:${Math.min(
            pos.y + this.pullDownInitTop,
            0
          )}px`;
        }
        if (this.isRebounding) {
          this.pullDownStyle = `top:${0 -
            (this.pullDownRefresh.stop - pos.y)}px`;
        }
      });
    },
    _reboundPullDown() {
      const { stopTime = 300 } = this.pullDownRefresh;
      return new Promise(resolve => {
        setTimeout(() => {
          this.isRebounding = true;
          this.scroll.finishPullDown();
          resolve();
        }, stopTime);
      });
    },
    disable() {
      // 代理better-scroll的disable方法
      this.scroll && this.scroll.disable();
    },
    enable() {
      // 代理better-scroll的enable方法
      this.scroll && this.scroll.enable();
    },
    refresh() {
      // 代理better-scroll的refresh方法
      this.scroll && this.scroll.refresh();
    },
    scrollTo() {
      // 代理better-scroll的scrollTo方法
      this.scroll && this.scroll.scrollTo.apply(this.scroll, arguments);
    },
    scrollToElement() {
      // 代理better-scroll的scrollToElement方法
      this.scroll && this.scroll.scrollToElement.apply(this.scroll, arguments);
    },
    destroy() {
      this.scroll.destroy();
    }
  },
  watch: {
    // 監(jiān)聽(tīng)數(shù)據(jù)的變化,延時(shí)refreshDelay時(shí)間后調(diào)用refresh方法重新計(jì)算,保證滾動(dòng)效果正常,如果是下拉刷新,時(shí)間稍微調(diào)整長(zhǎng)點(diǎn)
    listArr(nVal, oVal) {
      let times = 800;
      if (this.isPullingDown) {
        times = 800;
      } else {
        times = 30;
      }
      setTimeout(() => {
        this.refresh();
        this.forceUpdate();
      }, times);
    }
  }
};
</script>

<style scoped lang='less'>
.no-data {
  margin-top: 2.4rem;
}
.have-data {
  margin-top: 0.2rem;
}
.my-scroll {
  overflow: hidden;
  height: 100%;
  position: relative;
}
.pulldown-wrapper {
  height: 0.5rem;
  position: absolute;
  top: -9px;
  left: 0;
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  transition: all;
}
.scroll-content {
  position: relative;
  z-index: 2000;
}
.pull-up-box {
  width: 100%;
  height: 0.2rem;
  // margin: 0.2rem 0 0.2rem 0;
  color: #999;
  font-size: 14px;
}
.refresh-txt {
  height: 0.3rem;
  width: 1rem;
  border-radius: 3px;
  background-color: black;
  opacity: 0.7;
  color: #fff;
  z-index: 2999;
  position: fixed;
  top: 2rem;
  left: 50%;
  transform: translate(-50%, 0);
  line-height: 0.3rem;
}
</style>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容