如何为Contentful long text字段内的图片实现懒加载
实现long text字段内图片懒加载
你现在直接用生成的HTML字符串注入的话,有两种成本很低的改造方案:
- 方案1:直接处理HTML字符串给img标签加原生懒加载属性
原生loading="lazy"已经适配绝大多数现代浏览器,不需要引入额外依赖,你只需要在拿到HTML之后做一次预处理:
const addLazyLoadToHtml = (htmlStr) => { const parser = new DOMParser(); const doc = parser.parseFromString(htmlStr, 'text/html'); doc.querySelectorAll('img').forEach(img => { img.setAttribute('loading', 'lazy'); // 还可以额外加自定义类、占位图属性等 }); return doc.documentElement.innerHTML; } // 调用改造后再注入 const article = addLazyLoadToHtml(data.contentfulBlogPost.article.childMarkdownRemark.html);
不想用DOMParser也可以用正则替换,不过DOMParser的兼容性和容错性更好,不会误伤内容里的文本。
- 方案2:基于Markdown AST自定义渲染
如果需要更复杂的懒加载逻辑(比如低码占位、加载动画、自定义错误处理),可以在GraphQL查询时把返回html改成返回ast,遍历AST节点遇到图片类型时用你自己封装的带懒加载的图片组件渲染,完全不用处理HTML字符串,可控性更高。
是否需要换成rich text字段
如果你的文章内容里除了文本还有大量图片、嵌入块、自定义格式,更推荐使用rich text字段,相比long text的markdown格式,优势如下:
- 内容结构完全结构化,图片作为独立的资源节点存在,不需要从markdown/HTML里解析,不会出现资源关联错误
- 自定义渲染成本更低,不需要做字符串预处理,直接通过官方渲染工具指定每个节点的渲染逻辑即可
rich text字段渲染方法
以React为例,使用Contentful官方提供的@contentful/rich-text-react-renderer包即可快速渲染:
- 调整GraphQL查询,获取rich text的raw内容和关联资源:
query MyQuery { allContentfulBlogPost { nodes { article { raw references { ... on ContentfulAsset { contentful_id title url width height } } } } } }
- 自定义渲染逻辑,给图片加懒加载:
import { documentToReactComponents } from '@contentful/rich-text-react-renderer'; import { BLOCKS } from '@contentful/rich-text-types'; // 你自己封装的带懒加载的图片组件 import LazyImage from './LazyImage'; const renderOptions = { renderNode: { [BLOCKS.EMBEDDED_ASSET]: (node) => { const asset = node.data.target; return <LazyImage src={asset.url} alt={asset.title} width={asset.width} height={asset.height} /> } } } // 页面内直接渲染即可 <section className={styles.article}> {documentToReactComponents(JSON.parse(article.raw), renderOptions)} </section>
内容的提问来源于stack exchange,提问作者btm2424
相关产品推荐
相关产品推荐

