实现点击按钮复制文本

前言

  • 最近Codeforces新添了一键复制样例到剪贴板的功能(好像很早就有了),所以上网研究了下怎么实现这个功能,并自己复现了Codeforces上的样例框。

Javascript怎么实现?

  • 浏览器已经为我们提供了相应的方法:
document.execCommand("copy");

但该方法只能作用于可编辑区域的内容,即只能作用在input,textarea这种标签上,具有很大的局限性,但我们暂且先不管这个缺陷,先看下在input标签上我们怎么实现一键复制的功能。

  • 现在页面上有一个input标签,我们想要复制其中的内容,我们可以这样做:
<input id="demoInput" value="hello world">
<button id="btn">点我复制</button>
const btn = document.querySelector('#btn');
btn.addEventListener('click', () => {
    const input = document.querySelector('#demoInput');
    input.select();
    if (document.execCommand('copy')) {
        document.execCommand('copy');
        console.log('复制成功');
    }
})

即我们先获取相应的input元素,然后调用select方法选中input框里的内容,最后调用一开始提到的方法即可完成复制。

  • 那么再回到我们最初的问题,如果我想一键复制的标签内容是div或其他标签该怎么办?其实也很简单,我们只需要在点击的时候隐式的创建一个textarea标签,然后让它的内容等于我们要复制标签的内容,调用浏览器的方法去复制这个标签里的内容,最后移除掉这个标签即可,这样我们的需求就能很好的完成了,具体代码如下:
let textArea = document.createElement("textarea");
let input = document.querySelector("pre");

textArea.style.position = "absolute";
textArea.style.left = "-9999 px";
textArea.value = input.innerText;

document.body.appendChild(textArea);
textArea.select();
if (document.execCommand("copy")) {
    document.execCommand("copy");
    alert("The input has been copied into the clipboard.");
} else {
     alert("Ooops,the browser doesn't support this method!");
}
document.body.removeChild(textArea);

Codeforces样例框Demo代码

  • 基于上述,我们就可以仿照着写出样例框的demo了,代码如下:

  • html部分:

<div class="input">
        <div class="title">
            Input
            <button>copy</button>
        </div>
        <pre>4
0011
0011</pre>
</div>
  • css部分:
.input {
      border: 1px solid #888;
      width: 250px;
}

.title {
    border-bottom: 1px solid #888;
    text-transform: lowercase;
    font-family: Consolas, "Lucida Console", "Andale Mono", "Bitstream Vera Sans Mono", "Courier New", Courier;
    font-weight: bold;
    width: calc(100%-0.5em);
    height: 20px;
    line-height: 20px;
    padding: 0.25em;
}

button {
     float: right;
}

pre {
       background-color: #efefef;
       margin: 0px;
       padding: 0.25em;
       color: #800;
}
  • js部分:
let copy = document.querySelector("button");
copy.addEventListener("click", () => {
    let textArea = document.createElement("textarea");
    let input = document.querySelector("pre");

    textArea.style.position = "absolute";
    textArea.style.left = "-9999 px";
    textArea.value = input.innerText;

    document.body.appendChild(textArea);
    textArea.select();
    if (document.execCommand("copy")) {
        document.execCommand("copy");
        alert("The input has been copied into the clipboard.");
    } else {
        alert("Ooops,the browser doesn't support this method!");
    }
    document.body.removeChild(textArea);
});

一些bug

  • ios端的时候用原生的js会出现两个bug
    • 点击复制时屏幕下方会出现白屏抖动,仔细看是拉起键盘又瞬间收起
    • 无法复制
  • 第一个bug出现的原因是当文本框被选中时,会弹出虚拟键盘导致页面出现闪烁,我们要杜绝这个只需要将文本框设置为只读即可。
textArea.setAttribute('readonly', 'readonly');
  • 第二个bug出现的原因是在ios下并没有选中全部内容,我们需要使用另一个方法来选中内容,这个方法就是
textArea.setSelectionRange(0, textArea.value.length);

其他的库

  • 除了调用浏览器自带的API,网上也有人已经写好相关的库了,这里丢个链接不再赘述:https://clipboardjs.com/

参考资料

发表评论

电子邮件地址不会被公开。 必填项已用*标注