Concis组件库封装——List列表

简介: Concis组件库封装——List列表组件封装

您好,如果喜欢我的文章,可以关注我的公众号「量子前端」,将不定期关注推送前端好文~

列表组件的封装其实和Table有一定的相似,都是数据一列一列展示,因此列表组件也用到了懒加载和虚拟列表对大数据量时提供了解决方案。

组件库文档:
在这里插入图片描述
List.tsx:

import React, {
   
    createContext, useMemo, useState, useEffect, useRef } from 'react';
import {
   
    listProps, listHeaderStyle, listContentStyle } from './interface';
import Item from './item';
import './style/list.module.less';

export const ctx = createContext<any>({
   
   } as any); //顶层通信装置
const List = (props: listProps) => {
   
   
  const {
   
   
    style = {
   
   },
    dataSource,
    render,
    header,
    size = 'default',
    lazyLoad = false,
    defaultShowNum = 5,
    virtualListProps,
    virtualShowNum = 5,
  } = props;

  const contextProps = {
   
   
    size,
  };
  const [formatDataSrouce, setFormatDataSource] = useState([...dataSource]); //处理过的数据源
  const [scrollTop, setScrollTop] = useState(0);
  const listItemHeight = useRef<any>(null);

  const listContentRef = useRef<any>(null);
  const victurlListContentRef = useRef<any>(null);

  useEffect(() => {
   
   
    if (lazyLoad && defaultShowNum) {
   
   
      setFormatDataSource((old) => {
   
   
        old = dataSource.slice(0, defaultShowNum);
        return [...old];
      });
    } else if (virtualListProps) {
   
   
      let rowHeight = document.querySelector('.list-item')?.clientHeight as any;
      switch (size) {
   
   
        case 'default':
          rowHeight += 26;
          break;
        case 'small':
          rowHeight += 18;
          break;
        case 'large':
          rowHeight += 34;
          break;
      }
      listItemHeight.current = rowHeight;
      setFormatDataSource((old) => {
   
   
        old = dataSource.slice(0, virtualShowNum + 2);
        return [...old];
      });
    }
  }, []);

  const listHeaderStyle = useMemo(() => {
   
   
    //头部样式
    const defaultStyles: listHeaderStyle = {
   
   };
    switch (size) {
   
   
      case 'default':
        defaultStyles.padding = '12px 20px';
        break;
      case 'small':
        defaultStyles.padding = '8px 20px';
        break;
      case 'large':
        defaultStyles.padding = '16px 20px';
        break;
    }
    return defaultStyles;
  }, [size]);

  const listStyle = useMemo(() => {
   
   
    //表整体样式
    return style;
  }, [style]);
  const listContentStyle = useMemo(() => {
   
   
    //表正文样式
    const returnStyle: listContentStyle = {
   
   };
    if (lazyLoad && defaultShowNum) {
   
   
      returnStyle.height = '400px';
      returnStyle.overflow = 'scroll';
    }
    return returnStyle;
  }, [lazyLoad, defaultShowNum]);
  const scrollList = () => {
   
   
    const {
   
    scrollHeight, clientHeight, scrollTop } = listContentRef.current as any;
    const bottomTran = scrollHeight - clientHeight - scrollTop; //距离底部距离
    if (bottomTran === 0) {
   
   
      setTimeout(() => {
   
   
        setFormatDataSource((old) => {
   
   
          old = dataSource.slice(0, old.length + defaultShowNum);
          return [...old];
        });
      }, 500);
    }
  };
  const victurlScroll = () => {
   
   
    const startIndex = Math.floor(victurlListContentRef.current.scrollTop / listItemHeight.current);
    setScrollTop(victurlListContentRef.current.scrollTop);
    setFormatDataSource((old) => {
   
   
      old = dataSource.slice(startIndex, startIndex + virtualShowNum + 2);
      return [...old];
    });
  };

  return (
    <ctx.Provider value={
   
   contextProps}>
      <div className="rList" style={
   
   listStyle}>
        <div className="list-header" style={
   
   listHeaderStyle}>
          {
   
   header}
        </div>
        {
   
   virtualListProps ? (
          <div
            className="victurl-list-content"
            style={
   
   {
   
    height: virtualShowNum * listItemHeight.current + 'px' }}
            ref={
   
   victurlListContentRef}
            onScroll={
   
   victurlScroll}
          >
            <div
              className="victurl-relly-content"
              style={
   
   {
   
   
                height: dataSource.length * listItemHeight.current - scrollTop + 'px',
                transform: `translate(0, ${
     
     scrollTop}px)`,
              }}
            >
              {
   
   formatDataSrouce.map(render)}
            </div>
          </div>
        ) : (
          <div
            className="list-content"
            style={
   
   listContentStyle}
            ref={
   
   listContentRef}
            onScroll={
   
   scrollList}
          >
            {
   
   formatDataSrouce.map(render)}
          </div>
        )}
      </div>
    </ctx.Provider>
  );
};

interface ForwardRefListType
  extends React.ForwardRefExoticComponent<
    React.PropsWithoutRef<listProps> & React.RefAttributes<HTMLDivElement>
  > {
   
   
  <T = any>(
    props: React.PropsWithChildren<listProps<T>> & {
   
   
      ref?: React.Ref<HTMLDivElement>;
    },
  ): React.ReactElement;
  Item: typeof Item;
}

const ListComponent = React.forwardRef<HTMLDivElement, listProps>(List) as ForwardRefListType;
ListComponent.Item = Item;
ListComponent.displayName = 'List';

export default ListComponent;

Item.tsx:

import React, {
   
    FC, memo, useMemo, useContext } from 'react';
import {
   
    listItemProps } from './interface';
import {
   
    ctx } from './index';
import './style/item.module.less';

const Item: FC<listItemProps> = (props) => {
   
   
  const {
   
    children, style = {
   
   } } = props;
  const {
   
    size } = useContext(ctx);

  const listItemStyle = useMemo(() => {
   
   
    const defaultStyles = style;
    switch (size) {
   
   
      case 'default':
        defaultStyles.padding = '13px 20px';
        break;
      case 'small':
        defaultStyles.padding = '9px 20px';
        break;
      case 'large':
        defaultStyles.padding = '17px 20px';
        break;
    }
    return defaultStyles;
  }, [size]);
  return (
    <div className="list-item" style={
   
   listItemStyle}>
      {
   
   children}
    </div>
  );
};

export default memo(Item);

最后留一下React-View-UI组件库线上地址吧~

开源不易,欢迎学习和体验,喜欢请多多支持,有问题请留言。

目录
相关文章
|
5天前
四种解决”Arg list too long”参数列表过长的办法
这些方法都可以帮助你避免因参数列表过长而导致的错误。选择方法取决于具体情况和需求。
10 0
|
8天前
|
索引 容器
06-python数据容器-list列表定义/list的10个常用操作/列表的遍历/使用列表取出偶数
06-python数据容器-list列表定义/list的10个常用操作/列表的遍历/使用列表取出偶数
|
16天前
使用Vant框架的组件van-pull-refresh搭配van-list和van-card完成上滑加载更多列表数据,下拉刷新当前列表数据(等同于翻页功能)
使用Vant框架的组件van-pull-refresh搭配van-list和van-card完成上滑加载更多列表数据,下拉刷新当前列表数据(等同于翻页功能)
|
17天前
|
索引 Python
Python标准数据类型-List(列表)
Python标准数据类型-List(列表)
42 1
|
1月前
|
存储 安全 Java
Python教程第3章 | 集合(List列表、Tuple元组、Dict字典、Set)
Python 列表、无序列表、字典、元组增删改查基本用法和注意事项
51 1
|
1月前
|
存储 数据可视化 索引
Python中List列表的妙用
Python中List列表的妙用
18 0
|
1月前
|
存储 索引 Python
Python中的基础数据结构:列表(List)详解
本文将深入探讨Python中的基础数据结构——列表(List),包括其创建、访问、修改、常用操作以及背后的原理。通过示例代码,帮助读者更好地理解和应用列表。
22 0
|
1月前
|
存储 Python
Python中的列表(list)和元组(tuple)区别
Python中的列表(list)和元组(tuple)区别
24 0
|
1月前
|
存储 Python
python列表推导式(List Comprehension)
python列表推导式(List Comprehension)
22 0
|
2月前
|
Python
Python列表推导式——List
Python列表推导式——List
29 0