如何用Material UI实现类似CSS ol&li的层级有序列表?
实现Material UI风格的层级自动编号列表
Material UI的默认List组件确实没有原生支持自动编号的层级列表,但你可以通过两种方案实现需求,不用手动维护序号:
方案一:原生ol/li + Material UI样式复用
直接借助HTML原生的<ol>和<li>标签的自动编号能力,同时用MUI的样式工具(比如sx属性)匹配MUI组件的视觉风格,这种方式最简单高效:
import { Typography } from '@mui/material'; // 基于嵌套数组结构的状态变量渲染列表 const HierarchicalList = ({ items }) => { return ( <ol sx={{ paddingLeft: 3, listStyleType: 'decimal', margin: 0 }}> {items.map((item, index) => ( <li key={index} sx={{ paddingY: 1 }}> <Typography variant="body1">{item.title}</Typography> {/* 渲染子层级列表 */} {item.children && ( <ol sx={{ paddingLeft: 3, listStyleType: 'lower-alpha', marginTop: 0.5, marginBottom: 0 }}> {item.children.map((child, childIndex) => ( <li key={childIndex} sx={{ paddingY: 0.5 }}> <Typography variant="body2">{child.title}</Typography> </li> ))} </ol> )} </li> ))} </ol> ); };
这种方案完全利用原生HTML的编号逻辑,无需额外维护计数器,同时通过Typography和sx属性保证和MUI系统的样式统一。
方案二:基于MUI List组件 + CSS计数器
如果必须使用MUI的List/ListItem组件,可以通过CSS计数器实现自动编号,避免手动编写序号:
import { List, ListItem, Typography, styled } from '@mui/material'; // 自定义带计数器的主列表组件 const StyledMainList = styled(List)(({ theme }) => ({ counterReset: 'mainCounter', paddingLeft: theme.spacing(3), margin: 0, })); const StyledMainListItem = styled(ListItem)(({ theme }) => ({ counterIncrement: 'mainCounter', paddingLeft: 0, '&:before': { content: 'counter(mainCounter) ". "', fontWeight: 500, marginRight: theme.spacing(1), }, })); // 自定义子层级列表组件 const StyledChildList = styled(List)(({ theme }) => ({ counterReset: 'childCounter', paddingLeft: theme.spacing(4), marginTop: theme.spacing(0.5), marginBottom: 0, })); const StyledChildListItem = styled(ListItem)(({ theme }) => ({ counterIncrement: 'childCounter', paddingLeft: 0, '&:before': { content: 'counter(childCounter, lower-alpha) ". "', marginRight: theme.spacing(1), }, })); const MUIHierarchicalList = ({ items }) => { return ( <StyledMainList> {items.map((item, index) => ( <StyledMainListItem key={index}> <Typography variant="body1">{item.title}</Typography> {item.children && ( <StyledChildList> {item.children.map((child, childIndex) => ( <StyledChildListItem key={childIndex}> <Typography variant="body2">{child.title}</Typography> </StyledChildListItem> ))} </StyledChildList> )} </StyledMainListItem> ))} </StyledMainList> ); };
推荐的状态变量结构
不管用哪种方案,状态变量可以设计成嵌套对象数组,方便映射渲染:
const [listData, setListData] = useState([ { title: 'xxxx', children: [] }, { title: 'xxxx', children: [{ title: 'xxxx' }, { title: 'xxxx' }] }, { title: 'xxxx', children: [] }, { title: 'xxxx', children: [{ title: 'xxxx' }, { title: 'xxxx' }] }, ]);
内容的提问来源于stack exchange,提问作者EBDS
相关产品推荐
相关产品推荐

