vue3实现上拉刷新下拉刷新加载

2023年8月9日10:09:33

vue2请看这个

具体看我的码云项目

下拉刷新下拉加载

首先我们引入的是vant3组件
具体怎么引入就不描述了

完整代码

!<template>
  <div class="main">
    <!-- loading效果 -->
    <div class="header">
      <div>
        <div @click="popup"><van-icon name="bar-chart-o" size="20px" /></div>
        <div>{{ name == "" ? "全部" : typeMap[name] }}</div>
        <div></div>
      </div>
      <div>
        <ul>
          <li
            :class="{ active: index == num }"
            @click="btnScroll(item, index)"
            v-for="(item, index) in tableList"
            :key="index">
            {{ typeMap[item] }}
          </li>
        </ul>
      </div>
    </div>
    <div class="sec">
      <ul>
        <van-pull-refresh
          success-text="刷新成功"
          v-model="isLoading"
          :head-height="80"
          @refresh="onRefresh"
        >
          <template #loosing>
            <img
              class="doge"
              src="https://fastly.jsdelivr.net/npm/@vant/assets/doge.png"
            />
          </template>
          <van-list
            v-model:loading="loading"
            :finished="finished"
            finished-text="没有更多了"
            @load="onLoad"
          >
            <li v-for="(item, index) in mainList" :key="index">
              <div>
                <span>
                  <a href="javascript"
                    ><img v-lazy="item.author.avatar_url"
                  /></a>
                </span>
                <span>
                  <span
                    :class="[
                      { ask: item.tab === 'ask' },
                      { share: item.tab === 'share' },
                      { job: item.tab === 'job' },
                      {
                        good: item.tab === 'good',
                        good: item.tab === 'dev',
                        top: item.top === true,
                      },
                    ]"
                  >
                    {{ item.top == true ? "置顶" : typeMap[item.tab] }}</span
                  >
                  <span>
                    <p>{{ item.title }}</p>
                    <p>
                      <span style="color: #333">{{ item.reply_count }}/</span
                      >{{ item.visit_count }}
                    </p>
                  </span>
                </span>
              </div>
              <div>{{ getLastTimeStr(item.create_at, true) }}</div>
            </li>
          </van-list>
        </van-pull-refresh>
      </ul>
    </div>
    <!-- 是否展示弹出层 -->
    <van-popup
      v-model:show="isshow"
      closeable
      close-icon="close"
      position="top"
      :style="{ width: '100%', height: '20%' }"
    >
      内容
    </van-popup>
  </div>
</template>
<script lang='ts'>
import * as api from "@/api/user"; //引入对应的api
import { getLastTimeStr } from "../utils/utils";
import {
  reactive,
  toRefs,
  onBeforeMount,
  onMounted,
  getCurrentInstance,
} from "vue";
import { useRouter, useRoute } from "vue-router"; //引入路由
export default {
  name: "",
  setup() {
    let router = useRouter(),
      route = useRoute();
    const { proxy } = getCurrentInstance() as any;
    const day = proxy.day;
    const data = reactive({
      isshow: false, //隐藏弹出层
      num: 0, //tab的index
      name: "", //tab的item
      type: {
        //请求接口的入参
        page: 1,
        tab: "all",
        limit: 18,
        total: 100, //这个总数是显示数据总数100就不加载刷新了
      },
      loading: false, //vant中的loading效果
      isLoading: false,
      finished: false, //加载完成后的效果
      mainList: [],
      getLastTimeStr(time: string, friendly: boolean) {
        return getLastTimeStr(time, friendly);
      },
      typeMap: {
        all: "全部",
        ask: "问答",
        share: "分享",
        job: "招聘",
        good: "精华",
        dev: "测试",
      },
      tableList: ["all", "good", "share", "ask", "job", "dev"],
    });
    const popup = () => {
      data.isshow = true;
    };
    const btnScroll = (item: any, index: number) => {
      //打印带参数的加个数据类型
      data.num = index;
      data.name = item;
      data.type.page = 1;//点击的时候默认显示页为1(初始化)
      getList();
    };
    const onRefresh = () => {
      setTimeout(() => {
        data.isLoading = false;
        data.type.page = 1;
        getList();
        data.loading = false;
      }, 800);
    };
    var time = 0;
    const onLoad = () => {
    // 如果加载2次的话 要判断初始化进来的时候
    // 判断不上拉加载
    if (time != 0) {
        getList();
      }
      time++;
    };
    const getList = () => {
      //请求接口数据
      let para = {
        page: data.type.page,
        limit: data.type.limit,
        tab: data.name == "" ? "all" : data.name,
      };
      api
        .topics(para)
        .then((res: any) => {
          setTimeout(() => {
            data.mainList =
              data.type.page == 1
                ? res.data.data
                : [...data.mainList, ...res.data.data];
            data.type.page++;
            data.finished = data.mainList.length >= data.type.total;
            data.loading = false;
          }, 800);
          if (data.type.page >= data.type.total) {
            data.finished = true;
            data.loading = false;
          }
        })
        .catch((err) => {
          data.loading = true; //错误loading打开
        });
    };
    onMounted(() => {
      getList();
    });
    const refData = toRefs(data);
    return {
      ...refData,
      popup,
      btnScroll,
      day,
      onLoad,
      onRefresh,
    };
  },
};
</script>
<style lang="scss" scoped>
.main {
  height: 100vh;
  background-color: #f6f6f6;
  .header::-webkit-scrollbar,
  .sec::-webkit-scrollbar {
    display: none;
  }
  .header {
    height: 80px;
    line-height: 80px;
    display: flex;
    flex-direction: column;
    > :nth-of-type(1) {
      height: 40px;
      line-height: 40px;
      box-sizing: border-box;
      display: flex;
      justify-content: space-between;
    }
    ::-webkit-scrollbar {
      display: none;
    } //去掉滚动样式
    > :nth-child(2) {
      width: 120%;
      overflow-x: scroll;
      height: 20px !important;
      line-height: 20px;
      box-sizing: border-box;
      padding: 15px 0;
      flex: 1;
      ul {
        width: 120%;
        height: 20px;
        box-sizing: border-box;
        .active {
          background-color: #80bd01;
          color: #fff;
          padding: 0 5px;
          height: 30px;
          line-height: 20px;
          border-radius: 3px;
          box-sizing: border-box;
        }
        li {
          width: auto;
          padding: 0 20px;
          height: 30px;
          float: left;
          box-sizing: border-box;
        }
      }
    }
  }
  .sec {
    overflow-y: scroll;
    height: calc(100% - 40px);
    background-color: white;
    .doge {
      width: 140px;
      height: 72px;
      margin-top: 8px;
      border-radius: 4px;
    }
    ul {
      height: 50px;
      li {
        height: 100%;
        display: flex;
        vertical-align: middle;
        justify-content: space-between;
        border-bottom: 0.5px solid rgb(231, 225, 225);
        padding: 10px 8px 10px 10px;
        box-sizing: border-box;
        .ask {
          color: white;
          background: #3498db;
        }
        .share {
          color: white;
          background: #1abc9c;
        }
        .job {
          color: white;
          background: #3498db;
        }
        .good {
          color: white;
          background: #1abc9c;
        }
        .top {
          color: white;
          background: #e74c3c;
        }
        > :nth-of-type(1) {
          position: relative;
          > :nth-child(1) {
            img {
              width: 30px;
              height: 30px;
            }
          }
          > :nth-child(2) {
            margin-left: 10px;
            > :nth-of-type(1) {
              padding: 2px 3px;
              font-size: 13px;
              border-radius: 2px;
              position: absolute;
              top: 0;
            }
            > :nth-of-type(2) {
              display: inline-block;
              text-align: left;
              margin-left: 40px;
              > :nth-child(1) {
                width: 220px;
                color: #888;
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
                font-size: 15px;
              }
              > :nth-of-type(2) {
                font-size: 12px;
                margin-top: 5px;
                color: #888;
              }
            }
          }
        }
        > :nth-child(2) {
          font-size: 13px;
          color: gray;
        }
      }
    }
  }
}
</style>

  • 作者:小阳生煎
  • 原文链接:https://blog.csdn.net/m0_53912016/article/details/125664434
    更新时间:2023年8月9日10:09:33 ,共 4915 字。