better-scroll在vue的使用

某一个页面的列表使用better-scroll的上拉加载和下拉刷新功能,better-scroll被封装成vue的组件

1。页面中

 <my-scroll
        ref="myScroll"
        :startY="parseInt(startY)"
        :listArr="state.testList"  // 列表数据
        :haveDataFlag="state.listHaveDataFlag" //分页请求,下一页是否有数据的标识
        :pullup="pullupFlag" // 是否开启上拉加载
        @scrollEnd="onLoadFun" // 上拉加载的方法
        :pullDownRefresh="pullDownRefreshObj" // 是否派发下拉刷新
        @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) {
// 如果下一页没有数据,停止上拉加载
        this.pullupFlag = false;
        return;
      }
// 请求接口
      await this.listRequest();
    },
    // 下拉刷新
    async onPullingDown() {
    //打印this可以看到_isDestroyed,当前实例是否已经被销毁
      if (this._isDestroyed) return;
      await this.updateInfo({
        stockMarketPageNum: 1, // 行情列表分页
        stockMarketList: [], // 行情列表
        nextStockMarketList: [] //行情新请求列表
      });
      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">没有更多数据了</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 滚动的时候会派发scroll事件,会截流。
     * 2 滚动的时候实时派发scroll事件,不会截流。
     * 3 除了实时派发scroll事件,在惯性或动画的情况下仍然能实时派发scroll事件
     */
    probeType: {
      type: Number,
      default: 1
    },
    /**
     * 点击列表是否派发click事件
     */
    click: {
      type: Boolean,
      default: true
    },
    /**
     * 是否开启横向滚动
     */
    scrollX: {
      type: Boolean,
      default: false
    },
    /**
     * 是否派发滚动事件
     */
    listenScroll: {
      type: Boolean,
      default: false
    },
    /**
     * 列表的数据
     */
    listArr: {
      type: Array,
      default: null
    },
    /**
     * 是否派发滚动到底部的事件,用于上拉加载
     */
    pullup: {
      type: Boolean,
      default: false
    },
    /**
     * 是否派发顶部下拉的事件,用于下拉刷新
     */
    pullDownRefresh: {
      type: null,
      default: false
    },
    /**
     * 是否派发列表滚动开始的事件
     */
    beforeScroll: {
      type: Boolean,
      default: false
    },
    /**
     * 当数据更新后,刷新scroll的延时。
     */
    refreshDelay: {
      type: Number,
      default: 20
    },
    bounce: {
      // 当滚动超过边缘的时候会有一小段回弹动画
      type: Boolean,
      default: true
    },
    fatherNeedPullFlag: {
      // 是否展示底部加载动画和文字
      type: Boolean,
      default: true
    },
    // nextListArr: { // 下次请求的新数据
    //   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, // 回弹动画
        pullup: this.pullup,
        pullDownRefresh: this.pullDownRefresh,
        taps: true,
        click: true
      };
      // better-scroll的初始化
      this.scroll = new BScroll(this.$refs.myScroll, options);
      // 是否派发滚动事件
      if (this.listenScroll) {
        this.scroll.on("scroll", pos => {
          this.$emit("scroll", pos);
        });
      }
      // 是否派发滚动到底部事件,用于上拉加载
      if (this.pullup) {
        this.scroll.on("scrollEnd", () => {
          // 滚动到底部
          if (this.scroll.y <= this.scroll.maxScrollY + 50) {
            this.$emit("scrollEnd");
          }
        });
      }
      // 监听滚动高度
      if (this.scrollFun) {
        this.scroll.on("scroll", scrollValue => {
          // 滚动到底部
          // console.log(scrollValue.y)
          this.$emit("scrollFun", scrollValue);
        });
      }

      // 是否派发顶部下拉事件,用于下拉刷新
      if (this.pullDownRefresh) {
        this._initPullDownRefresh();
      }
      // 是否派发列表滚动开始的事件
      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: {
    // 监听数据的变化,延时refreshDelay时间后调用refresh方法重新计算,保证滚动效果正常,如果是下拉刷新,时间稍微调整长点
    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>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容