uniapp 上拉刷新下拉加载

<template>
  <view>
    <movable-area
      style="width: 100%;height: 100%;"
      :style="{ height: scrollHeight + 50 + 'px' }"

    >
      <view
        class="display_flex_center"
        style="height: 40px; font-size: 15px; color: #6b6a6a"
      >
        <view v-if="refreshSuccess">
          {{ refreshSuccessText }}
        </view>
        <block v-else>
          <view  v-if="!refreshing"  class="refresh-icon display_flex_center" :class="{ 'refresh-icon-active': refreshFlag }" ></view>
          <view v-if="!refreshing">{{
            refreshFlag ? refreshReady : refreshText
          }}</view>
          <view v-else class="display_flex_center">
            <image src="https://caishentongweb.oss-cn-hangzhou.aliyuncs.com/mp-weixin/loading.gif" class="loading_img"></image>
            <text>{{ refreshingText }}</text>
          </view>
        </block>
      </view>
      <movable-view
        :x="x"
        :y="y"
        :direction="isRefresh ? 'vertical' : 'none'"
        :out-of-bounds="false"
        style="width: 100%"
        :style="{ height: scrollHeight + 'px' }"
        @change="onChange"
        @touchend="touchend"
      >
        <view :style="{ height: scrollHeight + 'px' }">
          <scroll-view
            :scroll-y="scrollStatus"
            :style="{
              height: scrollHeight + 'px',
              background: backgroundColor,
            }"
            :scroll-into-view="top_viewId"
            :upper-threshold="10"
            @scroll="onScroll"
            @scrolltoupper="scrollToTop"
            @scrolltolower="loadMore"
          >
            <view id="top_view" @touchstart="touchstart" @touchmove="touchMove">
              <slot></slot>
            </view>
            <view
              class="display_flex_center"
              style="height: 40px; font-size: 15px; color: #999"
            >
              <block v-if="noMore">
                {{ noMoreText }}
              </block>
              <block v-else-if="isLoading != 2">
                {{ loadingMoreText }}
              </block>
              <block v-else>
                {{ loadingText }}
              </block>
            </view>
            <view
              v-if="showGoTop && scrollTop > scrollHeight"
              class="go_top_icon_back"
              @click.stop="goTop"
            >
              <image src="https://caishentongweb.oss-cn-hangzhou.aliyuncs.com/mp-weixin/go_top.png" class="top_icon"></image>
            </view>
          </scroll-view>
        </view>
      </movable-view>
    </movable-area>
  </view>
</template>

<script>
export default {
  name: "zyq-movableRefresh",
  props: {
    isRefresh: {
      type: Boolean,
      default: true,
    },
    scrollHeight: {
      type: Number,
      default: 300,
    },
    refreshText: {
      type: String,
      default: "下拉可以刷新",
    },
    refreshReady: {
      type: String,
      default: "释放立即刷新",
    },
    refreshingText: {
      type: String,
      default: "正在刷新...",
    },
    refreshSuccessText: {
      type: String,
      default: "刷新完成",
    },
    loadingMoreText: {
      type: String,
      default: "上拉加载更多",
    },
    loadingText: {
      type: String,
      default: "正在加载...",
    },
    noMoreText: {
      type: String,
      default: "已经到底了~",
    },
    pullHeight: {
      type: Number,
      default: 40,
    },
    noMore: {
      type: Boolean,
      default: false,
    },
    backgroundColor: {
      type: String,
      default: "#eee",
    },
    showGoTop: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      x: 50,
      y: 0,
      old: {
        x: 0,
        y: 0,
      },
      refreshFlag: false,
      refreshing: false,
      scrollStatus: true,
      isLoading: 0, //加载状态,1:正在下拉刷新,2:正在触底加载
      refreshSuccess: false,
      scrollTop: 0,
      startX: 0,
      startY: 0,
      inTop: true,
      moveHeight: 0, //下拉刷新移动距离
      showLoadingMore: false,
      top_viewId: "",
    };
  },
  methods: {
    onChange(e) {
      let y = e.detail.y;
      this.old.x = e.detail.x;
      this.old.y = y;
      this.moveHeight = y;
      if (y < this.pullHeight) {
        this.refreshFlag = false;
      } else {
        this.refreshFlag = true;
      }
    },
    touchstart(e) {
      let obj = e.changedTouches[0];
      this.startX = obj.pageX;
      this.startY = obj.pageY;
    },
    touchMove(e) {
      if (!this.isRefresh) {
        return;
      }
      this.refreshSuccess = false;
      let obj = e.changedTouches[0];
      let endX = obj.pageX;
      let endY = obj.pageY;
      let distanceX = endX - this.startX;
      let distanceY = endY - this.startY;
      if (
        (this.inTop || this.scrollTop == 0) &&
        Math.abs(distanceX) < Math.abs(distanceY) &&
        distanceY > 0
      ) {
        this.scrollStatus = false;
      }
    },
    touchend(e) {
      let that = this;
      let moveHeight = this.moveHeight;
      if (moveHeight < this.pullHeight) {
        this.x = this.old.x;
        this.y = this.old.y;
        this.$nextTick(function () {
          this.x = 0;
          this.y = 0;
        });
        this.refreshFlag = false;
        this.refreshing = false;
      } else {
        this.refreshing = true;
        this.refreshFlag = true;
        this.refresh();
      }
      this.scrollStatus = true;
    },
    scrollToTop(e) {
      if (this.scrollTop < 5) {
        this.inTop = true;
      }
    },
    onScroll(e) {
      let scrollTop = e.detail.scrollTop;
      this.scrollTop = scrollTop;
      this.$emit("onScroll", scrollTop);
      if (scrollTop > 3) {
        this.inTop = false;
      } else {
        this.inTop = true;
      }
    },
    goTop() {
      this.top_viewId = "";
      this.$nextTick(function () {
        this.top_viewId = "top_view";
      });
    },
    runRefresh(callback = false) {
      let that = this;
      this.x = this.old.x;
      this.y = this.old.y;
      this.$nextTick(function () {
        this.scrollTop = 0;
        this.x = that.pullHeight;
        this.y = that.pullHeight;
        that.refreshing = true;
        that.refreshFlag = true;
        that.refresh();
      });
    },
    refresh() {
      if (this.isLoading) {
        return;
      }
      this.isLoading = 1;
      this.$emit("refresh");
    },
    loadMore() {
      if (this.noMore || this.isLoading) {
        return;
      }
      this.isLoading = 2;
      this.$emit("loadMore");
    },
    endLoad() {
      let that = this;
      this.refreshSuccess = true;
      setTimeout(function () {
        that.refreshSuccess = false;
      }, 800);
      this.x = this.old.x;
      this.y = this.old.y;
      this.$nextTick(function () {
        this.x = 0;
        this.y = 0;
      });
      this.scrollStatus = true;
      this.refreshing = false;
      this.refreshFlag = false;
      this.isLoading = 0;
    },
  },
};
</script>

<style>
.display_flex_center {
  display: flex;
  justify-content: center;
  align-items: center;
}
.refresh-icon {
  width: 20px;
  height: 20px;
  font-weight: 700;
  transition-duration: 0.5s;
  transition-property: transform;
  transform: rotate(0deg);
}
.refresh-icon-active {
  transform: rotate(180deg);
}
.loading_img {
  width: 20px;
  height: 20px;
  margin-right: 5px;
}
.go_top_icon_back {
  position: fixed;
  right: 40px;
  bottom: 40px;
  height: 40px;
  width: 40px;
  border-radius: 50%;
  background: #f5f7fa;
  display: flex;
  justify-content: center;
  align-items: center;
}
.top_icon {
  height: 30px;
  width: 30px;
}
</style>


使用--------------------------------------------
<template>
  <view class="content">
    <movable-refresh
      ref="movableRefresh"
      :scrollHeight="scrollHeight"
      :showGoTop="false"
      :noMore="noMore"
      :isRefresh="true"
      @refresh="refresh"
      @loadMore="loadMore"
      backgroundColor="#F5F7FA"
    >
      <view
        class="list-item display justify-content align-items"
        v-for="(item, index) in list"
        :key="index"
      >
        <view class="list-item-left">
          <image
            :src="Notify"
            class="list-item-img"
            :class="item.isRead ? 'read' : ''"
          />
        </view>
        <view class="list-item-right">
          <view class="list-item-right-top display justify-content align-items">
            <view class="list-item-right-title"
              >{{ item.title }}{{ index }}</view
            >
            <view class="list-item-right-time">{{ getTimer(item.time) }}</view>
          </view>

          <view class="list-item-right-bottom">
            <view class="list-item-right-content">{{ item.content }}</view>
          </view>
        </view>
      </view>
    </movable-refresh>
  </view>
</template>

<script>
import { getTimer } from "@/utils/getTimer.js";
import movableRefresh from "@/components/zyq-movableRefresh/zyq-movableRefresh.vue";

export default {
  components: {
    movableRefresh,
  },
  data() {
    return {
      getTimer,
      Notify:
        "https://caishentongweb.oss-cn-hangzhou.aliyuncs.com/mp-weixin/messageNotify.png",
      scrollHeight: 100,
      total: 30,
      noMore: false,
      list: [
        {
          id: 1,
          title: "休假申请",
          content: "您有一条休假申请待处理",
          time: "2022-10-10 10:10:10",
          isRead: false,
        },
        {
          id: 1,
          title: "休假申请",
          content: "您有一条休假申请待处理",
          time: "2022-10-10 10:10:10",
          isRead: false,
        },
        {
          id: 1,
          title: "休假申请",
          content: "您有一条休假申请待处理",
          time: "2022-10-10 10:10:10",
          isRead: false,
        },
        {
          id: 1,
          title: "休假申请",
          content: "您有一条休假申请待处理",
          time: "2022-10-10 10:10:10",
          isRead: false,
        },
        {
          id: 1,
          title: "休假申请",
          content: "您有一条休假申请待处理",
          time: "2022-10-10 10:10:10",
          isRead: false,
        },
        {
          id: 1,
          title: "休假申请",
          content: "您有一条休假申请待处理",
          time: "2022-10-10 10:10:10",
          isRead: false,
        },
        {
          id: 1,
          title: "休假申请",
          content: "您有一条休假申请待处理",
          time: "2022-10-10 10:10:10",
          isRead: false,
        },
      ],
      list1: [
        {
          id: 1,
          title: "休假申请",
          content: "您有一条休假申请待处理",
          time: "2022-10-10 10:10:10",
          isRead: false,
        },
        {
          id: 1,
          title: "休假申请",
          content: "您有一条休假申请待处理",
          time: "2022-10-10 10:10:10",
          isRead: false,
        },
        {
          id: 1,
          title: "休假申请",
          content: "您有一条休假申请待处理",
          time: "2022-10-10 10:10:10",
          isRead: false,
        },
        {
          id: 1,
          title: "休假申请",
          content: "您有一条休假申请待处理",
          time: "2022-10-10 10:10:10",
          isRead: false,
        },
        {
          id: 1,
          title: "休假申请",
          content: "您有一条休假申请待处理",
          time: "2022-10-10 10:10:10",
          isRead: false,
        },
        {
          id: 1,
          title: "休假申请",
          content: "您有一条休假申请待处理",
          time: "2022-10-10 10:10:10",
          isRead: false,
        },
      ],
    };
  },
  onLoad() {
    let system = uni.getSystemInfoSync();
    this.scrollHeight = system.windowHeight - 32;
  },
  methods: {
    refresh() {
      uni.showLoading({
        title: "加载中...",
        icon: "loading",
      });
      setTimeout(() => {
        this.list = this.list1;
        this.$refs["movableRefresh"].endLoad();
        uni.hideLoading();
      }, 2000);
    },

    getList() {
      uni.showLoading({
        title: "加载中...",
        icon: "loading",
      });
      setTimeout(() => {
        this.list = [...this.list, ...this.list1];
        this.$refs["movableRefresh"].endLoad();
        uni.hideLoading();
      }, 2000);
    },

    loadMore() {
      console.log(this.list.length);
      console.log(this.total);
      if (this.list.length > this.total || this.list.length == this.total) {
        this.noMore = true;
        uni.showToast({
          title: "没有更多了...",
          icon: "none",
          duration: 1000,
        });
        return;
      } else {
        this.getList();
      }
    },
  },
};
</script>

<style lang="scss" scoped>
.content {
  width: 100%;
  height: 100vh;
  background-color: $background-color;
  padding: 32rpx 24rpx;
  .list-item {
    padding: 34rpx 30rpx;
    border-radius: 24rpx;
    background: $uni-text-color-inverse;
    margin-bottom: 21rpx;
    &:last-child {
      margin-bottom: 0;
    }
    .list-item-right-title,
    .list-item-right-time,
    .list-item-right-content {
      font-family: PingFangSC_0;
      font-weight: 400;
    }

    .list-item-left {
      position: relative;
    }
    .read::after {
      border-radius: 50%;
      content: "";
      position: absolute;
      width: 16rpx;
      height: 16rpx;
      background: #ff0000;
      right: 0;
      top: 0;
    }

    .list-item-img {
      width: 94rpx;
      height: 94rpx;
    }
    .list-item-right {
      padding-left: 24rpx;
      flex: 1;
      .list-item-right-title {
        font-size: 32rpx;
        color: $uni-text-color;
        line-height: 45rpx;
      }
      .list-item-right-time {
        font-size: 24rpx;
        color: $uni-text-color-grey;
        line-height: 36rpx;
      }
      .list-item-right-content {
        font-size: 26rpx;
        color: $uni-text-color-grey;
        line-height: 36rpx;
      }
    }
  }
}
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值