npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

list-pull

v1.0.5

Published

一个用于 H5 的 vue 列表组件,基于vant的pull和list组件可以下拉刷新和上拉加载。 最简单参数是`apiList`。

Downloads

10

Readme

list-pull

一个用于 H5 的 vue 列表组件,基于vant的pull和list组件可以下拉刷新和上拉加载。 最简单参数是apiList

安装

# yarn add list-pull
npm i list-pull

简单使用

<template>
  <list-pull ref="listPull" :apiList="apiListFormat" class="list-pull">
    <template #item="item">
      <!-- item可以是组件 或 节点,能拿到item数据 -->
      <div class="item" :key="item.id">{{ item.name }}</div>
    </template>
  </list-pull>
</template>

<script>
import ListPull from 'list-pull';

export default {
  // ...
  methods: {
    async apiListFormat(params) {
      const res = await apiXX(params);
      const { status, data } = res.data;
      const isSuccess = status === 1;
      return { isSuccess, data };
    },
  },
};
</script>

item 里面记得加key属性

效果如下:list_pull4

页面特定高度元素内刷新

页面中如果特定元素限定高度内刷新的话,css 设定高度。 数据为空的时候,需要设定位置

.list-pull {
  height: 300px;
  overflow-y: auto;
}
/deep/ .empty {
  position: absolute;
  top: 10%;/* 根据自身情况设置*/
}

效果如下:list_pull3

条件变化需要更新数据

有时新增或者条件变化,需要手动刷新,重新请求数据

this.$refs.listPull.refresh()

属性

apiList - 必传

返回Promise的函数,参数主要是pageNo,返回值必须固定是{isSuccess:Boolean,data:[]},data 就是列表数据,数组形式

pageSize

分页数。默认 20

disabled

是否禁止刷新。默认是false

isDisabledPushSet

是否禁止下拉加载。默认是false

其他参数

  • textEnd,数据请求完的文本,默认是到底了~
  • successText,刷新成功的文本,默认是刷新成功
  • textEmpty,空状态的文本,默认是暂无数据~
  • imgEmpty,空状态的图像,默认是x_empty

组件逻辑

加载一定要分类

加载有三种情况:

  • 初始加载
  • 顶部下拉刷新加载
  • 底部上拉加载

这三种加载均需要分情况

组件代码和组件逻辑注释

<template>
  <van-pull-refresh
    v-model="isTopPullLoading"
    :success-text="textRefreshSuccess"
    @refresh="onTopPullRefresh"
    :disabled="isDisabledRefresh"
  >
    <template v-if="list.length">
      <van-list
        class="list"
        immediate-check
        v-model="isBottomPushLoading"
        :finished="isEnd"
        finished-text=""
        @load="onBottomPushLoad"
      >
        <template v-for="item in list">
          <slot name="item" v-bind="item"></slot>
        </template>
      </van-list>
      <div class="end-tip" v-if="isEnd">{{ textEnd }}</div>
    </template>
    <div class="empty" v-if="isShowEmptyStatus">
      <img class="img" :src="imgEmpty" alt="" />
      <div class="text">{{ textEmpty }}</div>
    </div>
  </van-pull-refresh>
</template>
<script>
import { PullRefresh as vanPullRefresh, List as vanList, Toast } from 'vant';
import 'vant/lib/pull-refresh/style';
import 'vant/lib/list/style';
const configInit = {
  isEnd: false,
  isInitLoading: false,
  pageNo: 1,
  isBottomPushLoading: false,
};

export default {
  name: 'list-pull',
  props: {
    apiList: Function,
    pageSize: {
      default: 10,
    },
    isDisabledRefreshSet: {
      default: false,
    },
    isDisabledPushSet: {
      default: false,
    },
    textEmpty: {
      default: '暂无数据~',
    },
    imgEmpty: {
      default:
        'https://blog-huahua.oss-cn-beijing.aliyuncs.com/blog/code/empty2.png',
    },
    textEnd: {
      default: '已经到底了~',
    },
    textRefreshSuccess: {
      default: '刷新成功',
    },
  },
  components: {
    vanPullRefresh,
    vanList,
  },
  data() {
    return {
      isAlreadyRequested: false,
      list: [],
      ...configInit,
      // 这个不放在configInit 因为下拉的时候 isTopPullLoading是true,此时请求结果还没回来,不能设置为false
      isTopPullLoading: false,
    };
  },

  mounted() {
    this.requestInit();
  },
  computed: {
    /**
     * 显示空状态同时满足两个条件
     *  1. 请求过了
     *  2. 空数据
     */
    isShowEmptyStatus() {
      return this.isAlreadyRequested && this.list.length === 0;
    },
    /**
     * 不能下拉刷新,任意满足一个条件
     *  - 设置了isDisabledRefreshSet
     *  - 显示空状态了
     */
    isDisabledRefresh() {
      return this.isDisabledRefreshSet || this.isShowEmptyStatus;
    },
  },

  methods: {
    /** 初始请求,需要显示加载图标,且请求完成之后,设置请求过的flag,以控制空状态的显示和是否能刷新 */
    async requestInit() {
      const toast = Toast.loading({
        message: '加载中...',
        forbidClick: true,
      });
      this.list = await this._apiListRequest();
      toast.clear();
      this.isAlreadyRequested = true;
    },

    /**
     * 顶部下拉刷新
     * 如果禁止下拉的话,isTopPullLoading始终为false,不会触发此函数
     * 下拉的时候,isTopPullLoading自动触发为true,触发onTopPullRefresh
     * 下拉主要是刷新,重置页面部分配置,然后请求,请求回来之后,手动设置isTopPullLoading,结束下拉加载状态
     * */
    async onTopPullRefresh() {
      this.updateData();
    },
    async updateData() {
      this._resetConfig();
      this.list = await this._apiListRequest();
      this.isTopPullLoading = false;
    },

    /**
     * 底部上拉加载
     * 上拉的时候,isBottomPushLoading自动触发为true,触发onBottomPushLoad
     * 不加载但可能触发上拉的情形:父组件不需要上拉加载、数据完结了、正在加载、正在刷新
     * 触发下拉加载
     *  1. 如果不能加载,直接isBottomPushLoading为false,结束上拉加载状态
     *  2. 如果能加载,页数加一再请求,请求成功之后,数据追加,设置isBottomPushLoading为false,结束上拉加载状态
     */
    async onBottomPushLoad() {
      const isDisabledPush =
        this.isDisabledPush ||
        this.isEnd ||
        this.isInitLoading ||
        this.isTopPullLoading;
      if (isDisabledPush) {
        this.isBottomPushLoading = false;
        return;
      }
      this.pageNo += 1;
      const newList = await this._apiListRequest();
      this.list = [...this.list, ...newList];
      this.isBottomPushLoading = false;
    },

    /**
     * 三种情况发生请求:初始请求、下拉刷新请求、上拉加载请求
     * 但三种请求前后的逻辑并不相同,这边抽离共同逻辑,只返回list数据,其他逻辑各自处理
     * 请求的参数,主要是pageNo,如果不成功,返回[],成功的话,list的数据少于pageSize,表示到底,返回data
     */
    async _apiListRequest() {
      const res = await this.apiList({
        pageNo: this.pageNo,
      });
      const { data, isSuccess } = res;
      if (!isSuccess) {
        return [];
      }
      this.isEnd = data.length < this.pageSize;
      return data;
    },
    /** 下拉刷新的时候,页面部分配置初始化 */
    async _resetConfig() {
      Object.keys(configInit).forEach((key) => {
        this[key] = configInit[key];
      });
    },
  },
};
</script>
<style scoped>
.end-tip {
  margin-top: 20px;
  padding-bottom: 20px;
  text-align: center;
  font-size: 12px;
  font-weight: 400;
  color: #bbbbbb;
  line-height: 17px;
}
.van-pull-refresh {
  /* 有一定的高度 可以滚动 */
  height: auto;
  overflow: auto;
  /* min-height: 100vh; */
  position: relative;
}
.empty {
  /* position: absolute; */
  left: 0;
  right: 0;
  top: 40%;
  text-align: center;
  z-index: 3;
  /* transform: translate(0, -40%); */
  margin-top: 30px;
  justify-content: center;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.img {
  display: block;
  width: 110px;
}
.text {
  font-size: 14px;
  font-weight: 300;
  color: #999999;
  line-height: 20px;
  margin-top: 10px;
}
</style>