You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React Markdown文件中添加「复制代码片段」功能?

为React渲染的Markdown文档添加代码复制功能

步骤1:安装依赖

先装好用的工具库,覆盖Markdown渲染、代码高亮和复制功能:

npm install react-markdown react-syntax-highlighter clipboard

步骤2:创建带复制按钮的代码块组件

新建CodeBlockWithCopy.jsx组件,把代码块和复制功能整合到一起:

import { useState } from 'react';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
import ClipboardJS from 'clipboard';

const CodeBlockWithCopy = ({ language, value }) => {
  const [copyStatus, setCopyStatus] = useState('复制');

  const handleCopy = () => {
    const codeId = `code-${Date.now()}`;
    const clipboard = new ClipboardJS(`#copy-${codeId}`, {
      text: () => value.trim()
    });

    clipboard.on('success', () => {
      setCopyStatus('已复制');
      setTimeout(() => setCopyStatus('复制'), 2000);
      clipboard.destroy();
    });

    clipboard.on('error', () => {
      setCopyStatus('复制失败');
      setTimeout(() => setCopyStatus('复制'), 2000);
      clipboard.destroy();
    });
  };

  const codeId = `code-${Date.now()}`;

  return (
    <div style={{ position: 'relative', margin: '1rem 0' }}>
      <button
        id={`copy-${codeId}`}
        onClick={handleCopy}
        style={{
          position: 'absolute',
          top: '8px',
          right: '8px',
          padding: '4px 8px',
          fontSize: '12px',
          cursor: 'pointer',
          backgroundColor: '#333',
          color: '#fff',
          border: 'none',
          borderRadius: '4px'
        }}
      >
        {copyStatus}
      </button>
      <SyntaxHighlighter
        language={language}
        style={vscDarkPlus}
        customStyle={{ borderRadius: '4px' }}
        id={codeId}
      >
        {value.trim()}
      </SyntaxHighlighter>
    </div>
  );
};

export default CodeBlockWithCopy;

步骤3:渲染单个Markdown页面

以page1.md为例,写一个页面组件,用自定义的代码块替换默认渲染:

import ReactMarkdown from 'react-markdown';
import CodeBlockWithCopy from './CodeBlockWithCopy';
import page1Content from './page1.md?raw'; // Vite环境加?raw,Webpack需配置raw-loader

const Page1 = () => {
  return (
    <div style={{ maxWidth: '800px', margin: '0 auto', padding: '2rem' }}>
      <ReactMarkdown
        components={{
          code({ node, inline, className, children, ...props }) {
            const match = /language-(\w+)/.exec(className || '');
            // 只给非行内的代码块加复制按钮
            return !inline && match ? (
              <CodeBlockWithCopy
                language={match[1]}
                value={String(children).replace(/\n$/, '')}
                {...props}
              />
            ) : (
              <code className={className} {...props}>
                {children}
              </code>
            );
          }
        }}
      >
        {page1Content}
      </ReactMarkdown>
    </div>
  );
};

export default Page1;

步骤4:适配多个Markdown文件

其他MD页面直接复用上面的逻辑,替换导入的MD文件就行。比如Page2:

import ReactMarkdown from 'react-markdown';
import CodeBlockWithCopy from './CodeBlockWithCopy';
import page2Content from './page2.md?raw';

const Page2 = () => {
  return (
    <div style={{ maxWidth: '800px', margin: '0 auto', padding: '2rem' }}>
      <ReactMarkdown
        components={{
          code({ node, inline, className, children, ...props }) {
            const match = /language-(\w+)/.exec(className || '');
            return !inline && match ? (
              <CodeBlockWithCopy
                language={match[1]}
                value={String(children).replace(/\n$/, '')}
                {...props}
              />
            ) : (
              <code className={className} {...props}>
                {children}
              </code>
            );
          }
        }}
      >
        {page2Content}
      </ReactMarkdown>
    </div>
  );
};

export default Page2;

额外说明

  • 用Webpack的话,得装raw-loader并配置配置文件,才能把MD文件导入成纯文本。
  • 按钮样式、代码高亮主题都可以自己改,比如换react-syntax-highlighter里的其他主题。

内容的提问来源于stack exchange,提问作者Mahendran V M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 00:27:08