产品经理:“一个简单的复制功能也能写出bug?”

问题

刚入职时,遇到了一个线上 bug,用户点击复制按钮没办法复制文本,产品经理震怒,"这么简单的一个功能也能出问题?当时是谁验收的?",因为我刚来还闲着,就把我派去解决这个问题。

我在排查问题时,发现该复制方法写在了一个自定义 hook 中,点进去查看就是简单的一个 navigator.clipboard.writeText()的方法,本地运行我又能复制成功。于是我怀疑是手机浏览器不支持这个 api便去搜索了一下。

Clipboard

MDN 上的解释:

剪贴板 Clipboard APINavigator 接口添加了只读属性 clipboard ,该属性返回一个可以读写剪切板内容的 Clipboard 对象。在 Web 应用中,剪切板 API 可用于实现剪切、复制、粘贴的功能。

只有在用户事先授予网站或应用对剪切板的访问许可之后,才能使用异步剪切板读写方法。许可操作必须通过取得权限 Permissions API (en-US)"clipboard-read" 和/或 "clipboard-write" 项获得。

浏览器兼容性

使用 document.execCommand() 降级处理

这里我也不清楚用户手机浏览器的版本是多少,那么这个 api 出现之前,是用的什么方法呢?总是可以 polyfill 降级处理的吧!于是我就查到了document.execCommand()这个方法:

  • document.execCommand("copy") : 复制;
  • document.execCommand("cut") : 剪切;
  • document.execCommand("paste") : 粘贴。

对比

Clipboard 的所有方法都是异步的,返回 Promise 对象,复制较大数据时不会造成页面卡顿。但是其支持的浏览器版本较新,且只允许 https 和 localhost 这些安全网络环境可以使用,限制较多。

document.execCommand() 限制较少,使用起来相对麻烦。但是 MDN 上提到该 api 已经废弃:

浏览器很可能在某个版本弃用该 api ,不过当前 2023/12/29 ,该复制 api 还是可以正常使用的。

具体代码修改

于是我修改了一下原来的 hook:

tsx 复制代码
import Toast from "~@/components/Toast";

export const useCopy = () => { 
    
  const copy = async (text: string, toast?: string) => {
      
    const fallbackCopyTextToClipboard = (text: string, toast?: string) => {
      let textArea = document.createElement("textarea");
      textArea.value = text;

      // Avoid scrolling to bottom
      textArea.style.top = "-200";
      textArea.style.left = "0";
      textArea.style.position = "fixed";
      textArea.style.opacity = "0"

      document.body.appendChild(textArea);
      // textArea.focus();
      textArea.select();
      let msg;
      try {
        let successful = document.execCommand("copy");
        msg = successful ? toast ? toast : "复制成功" : "复制失败";
      } catch (err) {
        msg = "复制失败";
      }
      Toast.dispatch({
        content: msg,
      });
      document.body.removeChild(textArea);
    }; 
      
    const copyTextToClipboard = (text: string, toast?: string) => {
      if (!navigator.clipboard || !window.isSecureContext) {
        fallbackCopyTextToClipboard(text, toast);
        return;
      }
      navigator.clipboard
        .writeText(text)
        .then(() => {
          Toast.dispatch({
            content: toast ? toast : "复制成功",
          });
        })
        .catch(() => {
          fallbackCopyTextToClipboard(text, toast)
        });
    };
    copyTextToClipboard(text, toast);
  };

  return copy;
};

上线近一年,这个复制方法没出现异常问题。

相关推荐
Setsuna_F_Seiei1 小时前
前端的 AI 学习之路 01 之 Agent API 调用 - 和 Agent 的基础对话
前端·人工智能·ai编程
threerocks2 小时前
AI 原生软件开发生命周期手册 - 如何借助 AI,逐阶段改造软件开发生命周期
前端·javascript·后端
徐小夕2 小时前
3分钟从想法到Agent上线:我们开源了一款AI可视化工作流“IDE”
前端·算法·github
ly76894 小时前
JavaScript 从入门到进阶:核心语法、异步编程与工程化实践
开发语言·javascript·ecmascript
why技术4 小时前
eli5,我觉得这个全网在吹的技能,使用体验真的很一般啊。
前端·人工智能·后端
excel4 小时前
记录升级 nuxt3 到 nuxt4 记录
前端
剑胆琴心静水深流5 小时前
全栈之路6---web集成与呈现
前端·vue.js·spring boot·分布式·spring·前端框架·npm
前端snow5 小时前
ai agent -- Memory汇总
前端
ITresearchGuest5 小时前
AI 焦虑下,前端该何去何从
前端·人工智能
沙盘客5 小时前
AFSIM 示例解读(03)· 六自由度飞行仿真 six_dof(下):机场运作与弹道导弹投送
java·javascript·经验分享