在 Next.js 应用中处理从 API 获取的文本中的内部链接是一个常见需求。这些链接可能是 Markdown 内容、富文本或纯 HTML 中的链接,需要被正确地解析并转换为 Next.js 的路由系统。
next/link
组件替换普通链接当从 API 获取的文本包含 HTML 时,可以使用 dangerouslySetInnerHTML
结合 DOM 操作或 HTML 解析器来替换链接。
import { useEffect, useRef } from 'react';
import Link from 'next/link';
function RichTextWithLinks({ htmlContent }) {
const contentRef = useRef(null);
useEffect(() => {
if (contentRef.current) {
const links = contentRef.current.querySelectorAll('a[href^="/"]');
links.forEach(link => {
const href = link.getAttribute('href');
const text = link.textContent;
const nextLink = document.createElement('span');
nextLink.innerHTML = `<Link href="${href}"><a>${text}</a></Link>`;
link.replaceWith(nextLink);
});
}
}, [htmlContent]);
return (
<div
ref={contentRef}
dangerouslySetInnerHTML={{ __html: htmlContent }}
/>
);
}
更安全的方法是使用像 html-react-parser
这样的库:
import parse from 'html-react-parser';
import Link from 'next/link';
function RichTextWithLinks({ htmlContent }) {
const options = {
replace: (domNode) => {
if (domNode.name === 'a' && domNode.attribs.href?.startsWith('/')) {
return (
<Link href={domNode.attribs.href} passHref>
<a {...domNode.attribs}>{domNode.children}</a>
</Link>
);
}
}
};
return <div>{parse(htmlContent, options)}</div>;
}
如果是 Markdown 内容,可以使用 remark
和 rehype
生态系统:
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
import rehypeReact from 'rehype-react';
import Link from 'next/link';
function MarkdownWithLinks({ markdown }) {
const result = unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypeReact, {
createElement: React.createElement,
components: {
a: ({ href, children }) => {
if (href.startsWith('/')) {
return (
<Link href={href} passHref>
<a>{children}</a>
</Link>
);
}
return <a href={href}>{children}</a>;
}
}
})
.processSync(markdown).result;
return <div>{result}</div>;
}
Link
组件实现客户端导航,避免完整页面刷新Link
组件指向的页面资源原因:没有使用 next/link
或使用不正确
解决:确保所有内部链接都包裹在 Link
组件中
原因:没有区分内部和外部链接
解决:在转换前检查链接是否以 /
开头或匹配你的域名
原因:替换链接时丢失了原始样式 解决:确保在转换时保留原始元素的类名和样式属性
通过以上方法,你可以有效地处理从 API 获取的文本中的内部链接,同时保持 Next.js 的路由优势。
没有搜到相关的文章