这是我参与「第五届青训营 」伴学笔记创作活动的第 15天 拖延症患者终于开始完善List组件了,简单的不依赖其他组件的一个手写List组件。 今天完成了bordered属性、size属性、renderItem属性、header属性和footer属性
| 属性 | 作用 |
|---|---|
| size | lg/sm 默认为中等大小 |
| borded | 有无框线 |
| renderItem | 当使用 dataSource 时,可以用 renderItem 自定义渲染列表项 |
| header | 表头 |
| footer | 表底 |
比较难的是renderItem的逻辑,首先传入的是函数renderItem(item: string, index: number) => React.ReactNode
例如:
<List dataSource={data} renderItem = {(item) => (<ul>
<img src = "./1.png" alt = "a picture" ></img>[ITEM] {item}</ul>)
}></List>
我们将源数据中的每一项解析到renderItem中,然后再生成childrenContext渲染到页面上。
React.Fragment组件能够在不额外创建 DOM 元素的情况下,让 render()方法中返回多个元素。相当于空标签<></>。<></>和Fragment标签的区别:Fragment标签支持能接受键值或属性,可以遍历循环渲染元素
const renderInnerItem = (item: string, index: number) => {
if (!renderItem) return null;
return <React.Fragment>{renderItem(item, index)}</React.Fragment>;
};
let splitDataSource = dataSource;
let childrenContent:ReactNode;
if (splitDataSource.length > 0) {
const items = splitDataSource.map((item: string, index: number) => renderInnerItem(item, index));
childrenContent = <div className={`ai-list`}>{items}</div>
}
list.tsx如下
import React, { ReactNode } from "react";
import "./style/list.scss"
import classNames from "classnames";
export type ListSize = "lg" | "md" | "sm";
interface ListProps{
dataSource : any[];
size ? : ListSize;
header ? : ReactNode;
footer ? : ReactNode;
bordered ? : boolean;
renderItem ?: (item: string, index: number) => React.ReactNode;
}
const List : React.FC<ListProps> = (props)=>{
const {
dataSource,
size,
header,
footer,
bordered,
renderItem
} = props;
const renderInnerItem = (item: string, index: number) => {
if (!renderItem) return null;
return <React.Fragment>{renderItem(item, index)}</React.Fragment>;
};
let splitDataSource = dataSource;
let childrenContent:ReactNode;
if (splitDataSource.length > 0) {
const items = splitDataSource.map((item: string, index: number) => renderInnerItem(item, index));
childrenContent = <div className={`ai-list`}>{items}</div>
}
const classes = classNames("ai-listItem", {
[`ai-li-${size}`]: size, // size 参数存在时动态添加 `ai-li-${size}` 类 , size:padding
});
const listclasses = classNames("ai-list", {
[`ai-li-bordered-${String(bordered)}`] : bordered,
}
)
return(
<>
<div className={listclasses}>
{ footer && <div className= {classes}>{header}</div>}
<>{
!renderItem &&
dataSource &&
dataSource.map(data =>(
<div className={classes}>
{data}
</div>
) ) } </>
{ renderItem && <>{childrenContent}</>}
{header && <div className={classes}>{footer}</div>}
</div></>
)
}
export default List;
效果图如下: