一、效果图


二、navigator.clipboard API

直奔主题。代码块复制使用现代浏览器原生 Clipboard API 🚀

const [copied, setCopied] = useState(false);
​
// 处理复制逻辑
const handleCopy = async (code: string) => {
  try {
    await navigator.clipboard.writeText(code);
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  } catch (err) {
    console.error('复制失败:', err);
  }
};
​
const codeContent = String(children).replace(/\n$/, '')
return(
  <button
    onClick={() => handleCopy(codeContent)}
    style={{
      position: 'absolute',
      right: 8,
      top: 8,
      padding: '4px 8px',
      background: '#f5f5f5',
      border: '1px solid #ddd',
      borderRadius: 4,
      cursor: 'pointer',
      zIndex: 1,
      opacity: copied ? 1 : 0.6,
      transition: "opacity 0.2s",
    }}
  >
    {copied ? '复制成功' : '⎘ 复制'}
  </button>
)

关键点说明 🔑

  1. 状态管理

    • 使用 useState 跟踪复制状态,提供视觉反馈

    • 2秒后自动重置复制状态提示

  2. 样式定位

    • 绝对定位到代码块右上角

    • 平滑过渡效果增强用户体验

  3. 使用方式

<div style={{position: 'relative'}}> //外层相对定位
  //复制
  {children && handCopyRender(children)} //复制块绝对定位
  //代码块dom
  //例:<SyntaxHighlighter/>
</div>
  1. 内容处理

    • const codeContent = String(children).replace(/\n$/, "");

    • 移除代码结尾的多余换行符,确保复制内容格式正确


三、浏览器兼容处理 🛡️

兼容性问题说明

  • 旧版浏览器不支持 Clipboard API

  • HTTP环境下无法生效

  • 浏览器安全限制:Clipboard API 要确保在 HTTPS 环境或 localhost 下使用

兼容性处理后完整代码:

const handCopyRender = (value: React.ReactNode) => {
  /** 复制功能组件 */
  const [copied, setCopied] = useState(false);
  
  // 兼容性复制方法
  const copyToClipboard = (text: string) => {
    return new Promise<boolean>((resolve) => {
      try {
        // 现代浏览器方案
        if (navigator.clipboard && window.isSecureContext) {
          navigator.clipboard.writeText(text)
            .then(() => resolve(true))
            .catch(() => resolve(false));
        } 
        // 旧浏览器兼容方案
        else {
          // 创建临时文本域
          const textArea = document.createElement('textarea');
          textArea.value = text;
          textArea.style.position = 'fixed';  // 避免滚动跳转
          textArea.style.opacity = '0';      // 透明不可见
          
          document.body.appendChild(textArea);
          textArea.focus(); //文本处于可编辑区域
          textArea.select(); //且被选中
​
          // 执行复制命令
          const success = document.execCommand('copy');
          document.body.removeChild(textArea);
          resolve(success);
        }
      } catch (err) {
        console.error("复制失败:", err);
        resolve(false);
      }
    });
  };
​
  const handleCopy = async () => {
    try {
      // 转换内容为字符串
      const codeContent = String(value).replace(/\n$/, "");
      
      // 执行复制操作
      const success = await copyToClipboard(codeContent);
      
      if (success) {
        setCopied(true);
        setTimeout(() => setCopied(false), 2000);
      } else {
        // 降级提示
        alert("自动复制失败,请手动选择文本后按 Ctrl+C");
      }
    } catch (err) {
      console.error("复制异常:", err);
    }
  };
​
  return (
    <button
      onClick={handleCopy}
      style={{
        position: 'absolute',
        right: 8,
        top: 8,
        padding: '4px 8px',
        background: '#f5f5f5',
        border: '1px solid #ddd',
        borderRadius: 4,
        cursor: 'pointer',
        zIndex: 1,
        opacity: copied ? 1 : 0.6,
        transition: "opacity 0.2s",
      }}
    >
      {copied ? '复制成功' : '⎘ 复制'}
    </button>
  );
};

关键点说明 🔍

  1. 环境检测

    navigator.clipboard && window.isSecureContext
    • window.isSecureContext 检测 HTTPS/本地环境

    • window.isSecureContext是一个浏览器 API,用于检查当前页面是否在安全上下文中运行。如果页面在安全上下文中运行(即通过HTTPS加载),则该函数返回true,否则返回false。

  2. 降级策略

    • 使用document.execCommand('copy')的旧方法

    • 创建临时textarea元素执行复制操作

    • 处理完立即移除元素,避免DOM污染

  3. 用户体验优化

    • 提供清晰的错误提示

    • 保留手动复制选项

    • 统一的视觉反馈


四、总结 🎯

本文介绍了两种代码复制实现方案:

  1. 现代方案:使用navigator.clipboard API,简洁高效

  2. 兼容方案:降级使用document.execCommand,确保全浏览器支持

关键思路

  • 创建临时textarea元素来执行复制操作

  • 处理各种边界情况和用户体验问题

  • 提供清晰的反馈和降级方案

适用场景

  • 代码编辑器

  • 技术文档网站

  • AI对话界面

  • 任何需要代码复制的Web应用

💡 小贴士:在实际项目中,可以将此功能封装成可复用的React组件,方便多处调用!

如果觉得本文有帮助,别忘了点赞收藏+关注哦!❤️

Logo

GitCode AI社区是一款由 GitCode 团队打造的智能助手,AI大模型社区、提供国内外头部大模型及数据集服务。

更多推荐