如何从Strapi富文本字段生成目录
如何从Strapi富文本数据生成目录
实现思路
Strapi的富文本(BlocksContent)是由不同类型的块组成的数组,其中标题类块(heading1/heading2/heading3等)包含目录所需的核心信息。可以通过以下三步实现目录功能:
- 从富文本数据中提取所有标题节点
- 为每个标题块添加锚点ID
- 渲染可跳转的目录组件
完整代码实现
import { BlocksRenderer, type BlocksContent, type Block } from "@strapi/blocks-react-renderer"; import { useGetBlogsByIdQuery } from "./your-gql-queries-path"; // 替换为你的GraphQL查询路径 // 提取标题节点的工具函数 const extractHeadings = (content: BlocksContent) => { if (!content) return []; return content.reduce((acc, block: Block) => { // 筛选所有标题类型的块 if (block.type.startsWith('heading')) { // 提取标题层级(如heading1对应层级1) const level = parseInt(block.type.replace('heading', ''), 10); // 拼接标题文本内容 const text = block.children?.map(child => child.text).join('') || ''; // 生成唯一锚点ID(文本slug化处理,避免特殊字符) const id = text.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, ''); acc.push({ id, text, level }); } return acc; }, [] as Array<{ id: string; text: string; level: number }>); }; const Blog = ({ slug }: { slug: string }) => { const { data } = useGetBlogsByIdQuery(slug); const content: BlocksContent = data?.data?.attributes?.content; // 提取标题生成目录数据 const tocItems = extractHeadings(content); // 自定义标题块渲染器,添加锚点ID const renderBlock = (block: Block) => { if (block.type.startsWith('heading')) { const level = parseInt(block.type.replace('heading', ''), 10); const text = block.children?.map(child => child.text).join('') || ''; const id = text.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, ''); // 根据层级渲染对应h1-h6标签并添加锚点ID const HeadingTag = `h${level}` as keyof JSX.IntrinsicElements; return <HeadingTag id={id}>{text}</HeadingTag>; } // 其他类型块使用默认渲染逻辑 return null; }; return ( <div className="blog-container"> {/* 渲染目录 */} {tocItems.length > 0 && ( <div className="table-of-contents"> <h3>目录</h3> <ul> {tocItems.map(item => ( <li key={item.id} style={{ marginLeft: `${(item.level - 1) * 16}px` }}> <a href={`#${item.id}`}>{item.text}</a> </li> ))} </ul> </div> )} {/* 渲染富文本内容,使用自定义标题渲染器 */} <BlocksRenderer content={content} renderBlock={renderBlock} /> </div> ); }; export default Blog;
关键细节说明
- 标题提取:通过
extractHeadings遍历富文本块数组,筛选标题块后提取文本、层级,并生成唯一锚点ID(slug化处理避免特殊字符冲突)。 - 自定义标题渲染:借助
BlocksRenderer的renderBlock属性,为每个标题标签添加对应id,实现锚点跳转的基础。 - 目录样式:通过
marginLeft根据标题层级设置缩进,模拟多级目录的视觉层级,可根据需求调整样式规则。
扩展优化建议
- 若存在重复标题文本,可在生成ID时追加索引(如
my-heading-1、my-heading-2)避免锚点重复。 - 可添加滚动监听逻辑,高亮当前浏览位置对应的目录项。
- 长文章场景下,可将目录固定在侧边,提升用户浏览体验。
内容的提问来源于stack exchange,提问作者Damilola Adegbemile
相关产品推荐
相关产品推荐

