前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >Vue中下拉刷新和上拉加载更多

Vue中下拉刷新和上拉加载更多

作者头像
码客说
发布2021-08-31 17:52:33
发布2021-08-31 17:52:33
1.1K00
代码可运行
举报
文章被收录于专栏:码客码客
运行总次数:0
代码可运行

前言

下拉刷新

ZDropDownRefresh.vue

代码语言:javascript
代码运行次数:0
复制
<template lang="html">
  <div
    class="refresh-moudle"
    @touchstart="touchStart($event)"
    @touchmove="touchMove($event)"
    @touchend="touchEnd($event)"
    ref="myrefresh"
    :style="{ transform: 'translate3d(0,' + top + 'px, 0)' }"
  >
    <header class="pull-refresh">
      <slot name="pull-refresh">
        <div class="down-tip" v-if="dropDownState === 1 || dropDownState === 2">
          <i
            ref="icon"
            class="css-icon icon-upward"
            :class="{ active: dropDownState === 2 }"
          ></i>
          <span class="down-text" v-if="dropDownState === 1">{{
            dropDownInfo.downText
          }}</span>
          <span class="down-text" v-if="dropDownState === 2">{{
            dropDownInfo.upText
          }}</span>
        </div>
        <div class="refresh-tip" v-if="dropDownState === 3">
          <span class="refresh-text">{{ dropDownInfo.refreshText }}</span>
        </div>
      </slot>
    </header>
    <slot></slot>
  </div>
</template>
<script>
export default {
  props: {
    onRefresh: {
      type: Function,
      required: false,
    },
  },
  data() {
    return {
      defaultOffset: 40, // 默认高度, 相应的修改.releshMoudle的margin-top和.down-tip, .up-tip, .refresh-tip的height
      top: 0,
      scrollIsToTop: 0,
      startY: 0,
      isDropDown: false, // 是否下拉
      isRefreshing: false, // 是否正在刷新
      isDropInTop: false, //开始下拉时是否在滚动条已在最上面
      dropDownState: 1, // 显示1:下拉可以刷新, 2:松开立即刷新, 3:正在刷新数据中...
      dropDownInfo: {
        downText: "下拉可以刷新",
        upText: "松开立即刷新",
        refreshText: "正在刷新数据...",
        refreshImg: "loading.png",
      },
    };
  },
  created() {
    if (document.querySelector(".down-tip")) {
      // 获取不同手机的物理像素(dpr),以便适配rem
      this.defaultOffset =
        document.querySelector(".down-tip").clientHeight || this.defaultOffset;
    }
  },
  methods: {
    /**
     * 触摸开始,手指点击屏幕时
     * @param {object} e Touch 对象包含的属性
     */
    touchStart(e) {
      let dom = this.$refs["myrefresh"];
      this.scrollIsToTop =
        dom.scrollTop || window.pageYOffset || document.body.scrollTop; // safari 获取scrollTop用window.pageYOffset
      if (this.scrollIsToTop === 0) {
        this.startY = e.targetTouches[0].pageY;
        this.isDropInTop = true;
      } else {
        this.isDropInTop = false;
      }
    },

    /**
     * 接触点改变,滑动时
     * @param {object} e Touch 对象包含的属性
     */
    touchMove(e) {
      if (this.isDropInTop) {
        if (e.targetTouches[0].pageY > this.startY) {
          // 下拉
          this.isDropDown = true;
          if (!this.isRefreshing) {
            // 拉动的距离
            let diff =
              e.targetTouches[0].pageY - this.startY - this.scrollIsToTop;
            this.top =
              Math.pow(diff, 0.8) +
              (this.dropDownState === 3 ? this.defaultOffset : 0);
            if (this.top >= this.defaultOffset) {
              this.dropDownState = 2;
              e.preventDefault();
            } else {
              this.dropDownState = 1;
              // 去掉会导致ios无法刷新
              e.preventDefault();
            }
          }
        } else {
          this.isDropDown = false;
          this.dropDownState = 1;
        }
      }
    },

    /**
     * 触摸结束,手指离开屏幕时
     */
    touchEnd() {
      if (this.isDropInTop) {
        if (this.isDropDown && !this.isRefreshing) {
          if (this.top >= this.defaultOffset) {
            this.refresh();
            this.isRefreshing = true;
          } else {
            // cancel refresh
            this.isRefreshing = false;
            this.isDropDown = false;
            this.dropDownState = 1;
            this.top = 0;
          }
        }
      }
    },

    /**
     * 刷新
     */
    refresh() {
      this.dropDownState = 3;
      this.top = this.defaultOffset;
      setTimeout(() => {
        this.onRefresh(this.refreshDone);
      }, 300);
    },

    /**
     * 刷新完成
     */
    refreshDone() {
      this.isRefreshing = false;
      this.isDropDown = false;
      this.dropDownState = 1;
      this.top = 0;
    },
  },
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.refresh-moudle {
  width: 100%;
  height: calc(100% + 40px);
  margin-top: -40px;
  -webkit-overflow-scrolling: touch; /* ios5+ */
  overflow-y: scroll;
}

.pull-refresh {
  width: 100%;
  color: #999;
  height: 40px;
  transition-duration: 200ms;
  font-size: 18px;
}

.refresh-moudle .down-tip,
.up-tip,
.refresh-tip {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 40px;
}

.css-icon {
  display: inline-block;
  height: 1em;
  width: 1em;
  font-size: 20px;
  margin-right: 10px;
  box-sizing: border-box;
  text-indent: -9999px;
  vertical-align: middle;
  position: relative;
}

.css-icon::before,
.css-icon::after {
  content: "";
  box-sizing: inherit;
  position: absolute;
  left: 50%;
  top: 50%;
  -ms-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}

.icon-upward::before {
  height: 0.65em;
  width: 0.65em;
  border-style: solid;
  border-width: 2px 0 0 2px;
  -ms-transform: translate(-50%, -50%) rotate(45deg);
  transform: translate(-50%, -50%) rotate(45deg);
}

.icon-upward::after {
  height: 0.8em;
  border-left: 2px solid;
  top: 55%;
}

.icon-upward.active {
  transform: rotate(180deg);
  transition: transform 0.3s;
}

@keyframes anticlockwise {
  0% {
    transform: rotate(-180deg);
  }
  100% {
    transform: rotate(0deg);
  }
}

@keyframes clockwise {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(-180deg);
  }
}

.refresh-img {
  width: 35px;
  height: 35px;
  margin-right: 15px;
  animation: rotating 1.5s linear infinite;
}

@keyframes rotating {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(1turn);
  }
}
</style>

使用方式

代码语言:javascript
代码运行次数:0
复制
<template>
  <div class="home">
    <div class="msg_list">
      <z-refresh :onRefresh="onRefresh">
          <div class="msg_item" @click="notice_click">
            <div class="msg_top">11111</div>
            <div class="msg_info">
              123456
            </div>
            <div class="msg_time">2021-08-28</div>
          </div>
          
          <div class="loadmore" @click="onLoadMore">点击加载更多</div>
      </z-refresh>
    </div>
  </div>
</template>

<script>
import ZDropDownRefresh from "../components/ZDropDownRefresh";

export default {
  components: {
    "z-refresh": ZDropDownRefresh,
  },
  methods: {
    /**
     * 下拉刷新
     */
    onRefresh(done) {
      // 如果下拉刷新和上拉加载同时使用,下拉时初始化上拉的数据
      console.info("下拉刷新");
      done();
    },
    onLoadMore() {
      console.info("加载更多");
    },
  },
};
</script>
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-08-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
    • 下拉刷新
    • 使用方式
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档