这是一个完整的复制函数实现,先尝试使用现代的 Clipboard API,如果不成功则回退到传统的 execCommand 方法:

function copyToClipboard(text) {
  // 如果浏览器支持 Clipboard API
  if (navigator.clipboard && window.isSecureContext) {
    return navigator.clipboard.writeText(text)
      .then(() => {
        console.log('复制成功 (Clipboard API)');
        return true;
      })
      .catch(err => {
        console.warn('Clipboard API 复制失败,使用备用方法:', err);
        return execCopy(text);
      });
  } else {
    // 回退到 execCommand 方法
    return Promise.resolve(execCopy(text));
  }
}

function execCopy(text) {
  return new Promise((resolve, reject) => {
    try {
      // 创建一个临时的 textarea 元素
      const textArea = document.createElement('textarea');
      textArea.value = text;
      
      // 设置样式使其不可见
      textArea.style.position = 'fixed';
      textArea.style.top = '0';
      textArea.style.left = '0';
      textArea.style.opacity = '0';
      textArea.style.pointerEvents = 'none';
      textArea.style.zIndex = '-1';
      
      document.body.appendChild(textArea);
      
      // 选中文本
      textArea.select();
      textArea.setSelectionRange(0, 99999); // 对于移动设备
      
      // 执行复制命令
      const successful = document.execCommand('copy');
      document.body.removeChild(textArea);
      
      if (successful) {
        console.log('复制成功 (execCommand)');
        resolve(true);
      } else {
        reject(new Error('execCommand 复制失败'));
      }
    } catch (err) {
      reject(err);
    }
  });
}

// 使用示例
copyToClipboard('要复制的文本')
  .then(success => {
    if (success) {
      console.log('复制成功!');
      // 可以在这里添加成功提示
    }
  })
  .catch(err => {
    console.error('复制失败:', err);
    // 可以在这里添加失败提示
  });

// 或者使用 async/await
async function handleCopy() {
  try {
    const success = await copyToClipboard('要复制的文本');
    if (success) {
      console.log('复制成功!');
    }
  } catch (err) {
    console.error('复制失败:', err);
  }
}

这个实现的特点:

  1. 优先使用 Clipboard API:更现代、更安全的方法

  2. 自动回退机制:当 Clipboard API 失败或不支持时,自动使用 execCommand

  3. Promise 接口:统一的异步处理

  4. 完整的错误处理:捕获各种可能的错误

  5. 样式处理:临时元素不会影响页面布局

  6. 移动设备支持:使用 setSelectionRange 确保在移动设备上也能正常工作

使用注意事项:

  • Clipboard API 需要在安全上下文(HTTPS 或 localhost)中工作

  • 某些浏览器可能需要用户手势(如点击事件)才能执行复制操作

  • 在用户交互事件(如点击)中调用此函数会有更高的成功率

简化版本(如果不需要详细的错误处理):

async function copyText(text) {
  try {
    if (navigator.clipboard && window.isSecureContext) {
      await navigator.clipboard.writeText(text);
      return true;
    } else {
      const textArea = document.createElement('textarea');
      textArea.value = text;
      textArea.style.cssText = 'position:fixed;top:0;left:0;opacity:0;';
      document.body.appendChild(textArea);
      textArea.select();
      const result = document.execCommand('copy');
      document.body.removeChild(textArea);
      return result;
    }
  } catch (err) {
    console.error('复制失败:', err);
    return false;
  }
}

// 使用
copyText('要复制的文本').then(success => {
  console.log(success ? '复制成功' : '复制失败');
});