0.2.0 • Published 2 years ago

charge-waterfall v0.2.0

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

简介

一个使用纯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 标签图片底部内容盒子的 cwaterfall-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("触底");
    isLoading.value = true;
    // 模拟一个异步请求,拿到异步请求的数据之后塞进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;
0.1.2

2 years ago

0.2.0

2 years ago

0.1.3

2 years ago

0.1.6

2 years ago

0.1.5

2 years ago

0.1.0

3 years ago

0.1.1

3 years ago

0.0.9

3 years ago

0.0.8

3 years ago

0.0.7

3 years ago

0.0.6

3 years ago

0.0.5

3 years ago

0.0.4

3 years ago

0.0.3

3 years ago

0.0.2

3 years ago

0.0.1

3 years ago