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

@zhazhazhu/charge-waterfall

v0.2.2

Published

使用纯TypeScript编写的瀑布流工具插件,定宽不定高。简单好用,配置方便,纯中文提示,即插即用。适用于JS、Vue、React、Angular

Downloads

23

Readme

简介

一个使用纯TypeScript编写的瀑布流工具插件,定宽不定高。简单好用,配置方便,纯中文提示,即插即用。适用于 JS、Vue、React、Angular(暂时没提供 Demo)。具体的 Vue 和 React 相关 Demo 可以查看Git 仓库维护不易,欢迎大家多多 ♥star⭐♥,也欢迎各位发现了问题给我提 issue

安装

npm:

npm install --save charge-waterfall

yarn:

yarn add charge-waterfall

特性

  • 纯 TS 编写,拥有完善的类型提示
  • 拥有多个配置项
  • 自动定图片宽高
  • 默认占位图
  • 支持有图/无图模式
  • 支持开启图片加载完成后的淡入动画
  • 触底加载更多
  • 支持响应式渲染

使用

在 TS 中使用可以引入类型,如果没有用到 TS 可以不需要导入类型

import Waterfall, { TOptions, TDataSource } from "charge-waterfall";

const options: TOptions = {
  //具体的选项请看下面
};

const waterfall = new Waterfall(options);

//纯JS的话
const waterfall = new Waterfall({
  //具体选项
});

使用的注意事项

  • container 父盒子容器必须是个空容器,里面不能有其它的内容
  • 使用触底加载更多进行请求时记得加个锁(具体可以看下面的例子代码),否则有可能会进行重复请求

TOptions 字段

| 属性 | 描述 | 默认值 | | 类型 | | -------------------- | ------------------------------------------------------------------------------------------------------ | --------------------------- | ---- | --------------------------------------------------- | | container | 装载图片的父容器,必须是一个空的元素,如.container 或者 document.querySelector('.container') | null | 必填 | HTMLElement | string | null | | initialData | 初始化数据源 | [] | 必填 | TDataSource[] | | column | 水平方向展示的列数 | 2 | 可选 | number | | width | 每一列的宽度 | 容器宽度 / 列数 | 可选 | number | | gapX | 元素水平间距 | 0 | 可选 | number | | gapY | 元素垂直间距 | 0 | 可选 | number | | animation | 淡入动画配置, animation: {name: "动画名称", duration: "动画持续时间(单位: 秒 s)"} | 具体看下方 | 可选 | TAnimationOptions | | defaultImgUrl | 有图模式下,图片渲染失败时会显示默认占位图,如果默认占位图显示也失败就会显示 alt 设置的默认字段image | 无 | 可选 | string | | resizable | 是否开启响应式改变布局宽度 | true | 可选 | boolean | | bottomDistance | 触底事件触发时离底部的距离 | 100(单位:"px"),最小值: 100 | 可选 | number | | imgContainerClass | 渲染出来的图片容器的 class 属性 | waterfall-img-container | 可选 | string | | imgClass | 渲染出来的图片的 class 属性 | waterfall-img | 可选 | string | | bottomContainerClass | 装载 img 标签图片底部内容盒子的 c | waterfall-bottom-container | 可选 | string | | onClick | 点击对应的项,回调参数是对应项的 dataSource 和点击 event 事件 | 无 | 可选 | (dataSource: TDataSource, event: Event) => void | | render | 传入要渲染的元素模板字符串,例如 <div>Title</div>,回调参数是对应项的 dataSource | 无 | 可选 | (dataSource: TDataSource) => string |

TDataSource 类型

new Waterfall({
  //...其它配置项,
  initialData: [
    {
      src: "图片url地址",
      data: {
        //存放的自定义数据
      },
      alt: "图片裂开时加载的文字",
    },
  ],
});
interface TDataSource<T = any> {
  /** 图片url地址 */
  src?: string
  /** 自定义的data数据,如果在TS中使用可以通过泛型来定义data中的类型 */
  data?: T
  alt?: string
}

TAnimationOptions 动画配置

new Waterfall({
  //...其它配置项,
  animation: {
    name: "fadeInDown",
    duration: 0.5,
  },
});

目前支持 4 种动画效果,动画名称默认值为 none(不开启动画),duration 持续时间默认值为 0.5

  • 从上往下淡入 fadeInDown
  • 从下往上淡入 fadeInUp
  • 从左往右淡入 fadeInLeft
  • 从右往左淡入 fadeInRight
type TAnimationNames =
  | "none"
  | "fadeInDown"
  | "fadeInUp"
  | "fadeInLeft"
  | "fadeInRight";

interface TAnimationOptions {
  /** 动画名称 */
  name?: TAnimationNames;
  /** 动画持续时间,单位(秒:s) */
  duration?: number;
}

实例上的方法

waterfall.onReachBottom(() => {
  //回调函数
});
waterfall.loadMore([]);
waterfall.destroy();

| 方法名称 | 描述 | 入参类型 | | ------------- | ------------------------------------ | --------------------------------------- | | onReachBottom | 触底时触发的事件 | 回调函数 () => void | | loadMore | 加载更多元素,用来往容器中塞新数据 | 和 initialData 一样的类型 TDataSource[] | | destroy | 销毁监听的 scroll 事件和 resize 事件 | 无 |

默认生成的 DOM 结构

<div class="container">
  <div class="waterfall-img-container">
    <img class="waterfall-img" />
    //只有在render模式下才会渲染该标签
    <div class="waterfall-bottom-container">//render属性里的内容</div>
  </div>
</div>

使用方式

关于更加详尽的使用方式可以打开Git 仓库,查看相关的 demo。

关于 Vue

可以git clone https://github.com/JiquanWang99/charge-waterfall.git,把仓库克隆到本地之后,然后cd demo/vue-demo,然后执行npm install,再执行npm run dev便可以在本地查看 demo。

关于 React

把仓库克隆到本地后,cd demo/react-demo,然后npm install,执行npm run dev,可以在本地查看 demo。

Vue 中的使用方式

<script setup>
import { onMounted, ref } from "vue";
import Waterfall from "charge-waterfall";
const waterfall = ref();
const isLoading = ref(false);

const sleep = (wait = 1000) => {
  return new Promise((resolve) => {
    setTimeout(resolve, wait);
  });
};

onMounted(() => {
  waterfall.value = new Waterfall({
    container: ".container",
    initialData: [
      {
        src: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic1.win4000.com%2Fpic%2Ff%2F6f%2F54671164988.jpg&refer=http%3A%2F%2Fpic1.win4000.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1666666622&t=95db3cae5629d7e558f836e2320038f6",
      },
      {
        src: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fhbimg.huabanimg.com%2F23f17e4aaa6cb3efc5811b3fa4926445bad168857e3ef-vnIVkW_fw658&refer=http%3A%2F%2Fhbimg.huabanimg.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1666668009&t=0feeb63a4d37695a0e4da365a14620c3",
      },
      {
        src: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fplc.jj20.com%2Fup%2Fallimg%2Fmx14%2F031121231931%2F210311231931-5.jpg&refer=http%3A%2F%2Fplc.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1666668021&t=f6cdaf8a52d7f442631c30cade98d8da",
      },
      {
        src: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fplc.jj20.com%2Fup%2Fallimg%2Fmx14%2F031121231931%2F210311231931-5.jpg&refer=http%3A%2F%2Fplc.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1666668021&t=f6cdaf8a52d7f442631c30cade98d8da",
      },
      {
        src: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fplc.jj20.com%2Fup%2Fallimg%2Fmx14%2F031121231931%2F210311231931-5.jpg&refer=http%3A%2F%2Fplc.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1666668021&t=f6cdaf8a52d7f442631c30cade98d8da",
      },
      {
        src: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fplc.jj20.com%2Fup%2Fallimg%2Fmx14%2F031121231931%2F210311231931-5.jpg&refer=http%3A%2F%2Fplc.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1666668021&t=f6cdaf8a52d7f442631c30cade98d8da",
      },
      {
        src: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fplc.jj20.com%2Fup%2Fallimg%2Fmx14%2F031121231931%2F210311231931-5.jpg&refer=http%3A%2F%2Fplc.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1666668021&t=f6cdaf8a52d7f442631c30cade98d8da",
      },
    ],
    resizable: true,
    bottomDistance: 200,
    column: 2,
    defaultImgUrl:
      "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fhbimg.b0.upaiyun.com%2Ffbf18a5314f750da671711dfb176cf8791fbc687153d-g7YSBF_fw658&refer=http%3A%2F%2Fhbimg.b0.upaiyun.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1636300149&t=84cd1f7a4fe131edd66638bd44f3496d",
    render: () => `<div>哈哈哈哈哈</div>`,
    onClick: (data, event) => {
      console.log(data, event);
    },
  });

  waterfall.value.onReachBottom(async () => {
    if (isLoading.value) return;
    isLoading.value = true;
    console.log("触底");
    // 模拟一个异步请求,拿到异步请求的数据之后塞进loadMore里面
    await sleep(2000);

    // 异步请求拿到数据之后就可以通过loadMore方法插入了
    waterfall.value.loadMore([
      {
        src: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Flmg.jj20.com%2Fup%2Fallimg%2F1114%2F041621124255%2F210416124255-1-1200.jpg&refer=http%3A%2F%2Flmg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1666668021&t=38137d81528162e28293c8a64d5caa56",
        data: {
          name: `${Math.floor(Math.random() * 100)}`,
        },
      },
      {
        src: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.jj20.com%2Fup%2Fallimg%2Fmn02%2F1231201I024%2F2012311I024-4.jpg&refer=http%3A%2F%2Fpic.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1666668021&t=71b04264cbf60717c407550a0db1fef0",
        data: {
          name: `${Math.floor(Math.random() * 100)}`,
        },
      },
    ]);
    isLoading.value = false;
  });
});
</script>

<template>
  <div class="container"></div>
  <div v-if="isLoading" style="text-align: center; padding: 20px">
    加载更多中...
  </div>
</template>

<style scoped>
* {
  padding: 0;
  margin: 0;
}
</style>

React 中的使用方式

import { useEffect, useState } from "react";
import Waterfall from "charge-waterfall";

function App() {
  const [isLoading, setIsLoading] = useState(false);

  const sleep = (wait = 1000) => {
    return new Promise((resolve) => {
      setTimeout(resolve, wait);
    });
  };

  useEffect(() => {
    const waterfall = new Waterfall({
      container: ".container",
      initialData: [
        {
          src: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic1.win4000.com%2Fpic%2Ff%2F6f%2F54671164988.jpg&refer=http%3A%2F%2Fpic1.win4000.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1666666622&t=95db3cae5629d7e558f836e2320038f6",
        },
        {
          src: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fhbimg.huabanimg.com%2F23f17e4aaa6cb3efc5811b3fa4926445bad168857e3ef-vnIVkW_fw658&refer=http%3A%2F%2Fhbimg.huabanimg.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1666668009&t=0feeb63a4d37695a0e4da365a14620c3",
        },
        {
          src: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fplc.jj20.com%2Fup%2Fallimg%2Fmx14%2F031121231931%2F210311231931-5.jpg&refer=http%3A%2F%2Fplc.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1666668021&t=f6cdaf8a52d7f442631c30cade98d8da",
        },
        {
          src: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fplc.jj20.com%2Fup%2Fallimg%2Fmx14%2F031121231931%2F210311231931-5.jpg&refer=http%3A%2F%2Fplc.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1666668021&t=f6cdaf8a52d7f442631c30cade98d8da",
        },
        {
          src: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fplc.jj20.com%2Fup%2Fallimg%2Fmx14%2F031121231931%2F210311231931-5.jpg&refer=http%3A%2F%2Fplc.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1666668021&t=f6cdaf8a52d7f442631c30cade98d8da",
        },
        {
          src: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fplc.jj20.com%2Fup%2Fallimg%2Fmx14%2F031121231931%2F210311231931-5.jpg&refer=http%3A%2F%2Fplc.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1666668021&t=f6cdaf8a52d7f442631c30cade98d8da",
        },
        {
          src: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fplc.jj20.com%2Fup%2Fallimg%2Fmx14%2F031121231931%2F210311231931-5.jpg&refer=http%3A%2F%2Fplc.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1666668021&t=f6cdaf8a52d7f442631c30cade98d8da",
        },
      ],
      resizable: true,
      bottomDistance: 200,
      column: 2,
      defaultImgUrl:
        "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fhbimg.b0.upaiyun.com%2Ffbf18a5314f750da671711dfb176cf8791fbc687153d-g7YSBF_fw658&refer=http%3A%2F%2Fhbimg.b0.upaiyun.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1636300149&t=84cd1f7a4fe131edd66638bd44f3496d",
      render: () => `<div>哈哈哈哈哈</div>`,
      onClick: (data, event) => {
        console.log(data, event);
      },
    });

    // 这里的_isLoading是防止触底重复多次请求的
    let _isLoading = false;
    waterfall.onReachBottom(async () => {
      if (_isLoading) return;
      _isLoading = true;
      console.log("触底");
      // 这里的setIsLoading是用来做Loading状态渲染的
      setIsLoading(true);
      // 模拟一个异步请求,拿到异步请求的数据之后塞进loadMore里面
      await sleep(2000);
      setIsLoading(false);
      // 异步请求拿到数据之后就可以通过loadMore方法插入了
      waterfall.loadMore([
        {
          src: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Flmg.jj20.com%2Fup%2Fallimg%2F1114%2F041621124255%2F210416124255-1-1200.jpg&refer=http%3A%2F%2Flmg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1666668021&t=38137d81528162e28293c8a64d5caa56",
          data: {
            name: `${Math.floor(Math.random() * 100)}`,
          },
        },
        {
          src: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.jj20.com%2Fup%2Fallimg%2Fmn02%2F1231201I024%2F2012311I024-4.jpg&refer=http%3A%2F%2Fpic.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1666668021&t=71b04264cbf60717c407550a0db1fef0",
          data: {
            name: `${Math.floor(Math.random() * 100)}`,
          },
        },
      ]);
      _isLoading = false;
    });

    return () => {
      waterfall.destroy();
    };
  }, []);

  return (
    <>
      <div className="container"></div>
      {isLoading && (
        <div
          style={{
            padding: "20px",
            textAlign: "center",
          }}
        >
          加载更多中...
        </div>
      )}
    </>
  );
}

export default App;