目錄
- 怎麼使用JavaScript實作一個剪貼
- 上面的方法不是很完美我們優化一下
- 思考一個問題
- 使用react和typescript重寫和優化一下
- 如何使用copyme
- 原文參考
寫在最前面
- 有一個簡單的需求,使用者需要快捷的複制一些相關的資訊,然後進行下一步資訊的填寫。前端這裡需要做一個剪貼闆友善使用者體驗。想直接參考 react 使用的可以看 使用react和typescript改寫和優化一下
- 大概設計如下,有多條資訊,然後使用者可以點選右邊的複制 icon 進行快捷的複制。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAjM2EzLcd3LcJzLcJzdllmVldWYtl2PnBnauIGZlVGOiVjZjRWNwUjM0ETMiZjMhJWNmR2M5QTYhlDMvwFO0ADO0IDOtUGall3LcVmdhNXLwRHdo9CXt92YucWbpRWdvx2Yx5yazF2Lc9CX6MHc0RHaiojIsJye.jpg)
怎麼使用JavaScript實作一個剪貼闆
- 具體分為五步
- 1、建立一個
,把需要的文本放進textarea
中textarea
- 2、将
元素插入textarea
中。body
- 3、使用
方法選擇HTMLInputElement.select()
中的文本内容textarea
- 4、使用
複制document.execCommand('copy')
中的文本内容到剪貼闆textarea
- 5、從
删除body
元素textarea
- 1、建立一個
- code
const copyToClipboard = str => {
const el = document.createElement('textarea');
el.value = str;
document.body.appendChild(el);
el.select();
document.execCommand('copy');
document.body.removeChild(el);
};
複制
必要 api 參考
- developer.mozilla.org/zh-CN/docs/…
上面的方法不是很完美我們優化一下
- 這個方法不是在每個地方都能運作,由于 textarea 的插入和移除,有時候會出現頁面的頻閃和抖動
- 下面用 css 優化一下我們的 textarea 樣式,隐藏 textarea 的顯示。
const copyToClipboard = str => {
const el = document.createElement('textarea');
el.value = str;
el.setAttribute('readonly', '');
el.style.position = 'absolute';
el.style.left = '-9999px';
document.body.appendChild(el);
el.select();
document.execCommand('copy');
document.body.removeChild(el);
};
複制
思考一個問題
- 我們使用者在使用我們的剪貼闆之前可能已經選擇了已存在 html 中的文本内容了,是以我們這裡需要多加一些判斷防止遺漏使用者選擇的文本。
-
這些方法存儲使用者選擇的文本内容和解決範圍選擇的問題DocumentOrShadowRoot.getSelection(), Selection.rangeCount, Selection.getRangeAt(), Selection.removeAllRanges() and Selection.addRange()
const copyToClipboard = str => {
const el = document.createElement('textarea'); // Create a <textarea> element
el.value = str; // Set its value to the string that you want copied
el.setAttribute('readonly', ''); // Make it readonly to be tamper-proof
el.style.position = 'absolute';
el.style.left = '-9999px'; // Move outside the screen to make it invisible
document.body.appendChild(el); // Append the <textarea> element to the HTML document
const selected =
document.getSelection().rangeCount > 0 // Check if there is any content selected previously
? document.getSelection().getRangeAt(0) // Store selection if found
: false; // Mark as false to know no selection existed before
el.select(); // Select the <textarea> content
document.execCommand('copy'); // Copy - only works as a result of a user action (e.g. click events)
document.body.removeChild(el); // Remove the <textarea> element
if (selected) { // If a selection existed before copying
document.getSelection().removeAllRanges(); // Unselect everything on the HTML document
document.getSelection().addRange(selected); // Restore the original selection
}
};
複制
使用react和typescript改寫和優化一下
- 學習了上面的文章,結合産品的需求改寫一下相關代碼。
- 思路
- 1、首先建立一個 targetNode,設定絕對布局,赢藏我們的元素
- 2、document.getSelection() 已經由 window.getSelection() 替代了,具體流程如上
- 3、建立一個 result 标記能否能正常 使用剪貼功能,不能的傳回 false
- 4、删除這個 targetNode
function createNode(text) {
const node = document.createElement('div');
node.innerText = text;
node.style.cssText = 'position:absolute; top: 0; left: 0; height:0; width:0; pointer-events: none;';
document.body.appendChild(node);
return node;
}
export default function copyMe(text) {
const targetNode = createNode(text);
const range = document.createRange();
const selection = window.getSelection()!;
const selected = selection.rangeCount > 0
? selection.getRangeAt(0)
: false;
targetNode.focus(); // focus 我們需要的文本
range.selectNodeContents(targetNode);
if(selected){
selection.removeAllRanges();
selection.addRange(range);
}
let result;
try {
result = document.execCommand('copy');
} catch (e) {
result = false;
}
document.body.removeChild(targetNode);
return result;
}
複制
如何使用copyme
import React, { Fragment } from 'react';
import copyMe from 'utils/copyMe';
interface ItemProps {
value?: string | number;
}
const Item: React.FC<ItemProps> = props => {
const { value } = props;
const copyme = () => {
alert(copyMe(value) ? 'Copied!' : 'Failed!');
};
return (
<Fragment>
{value && (
<div>
{value}
<textarea value={value} readOnly></textarea>
<span onClick={copyme}></span>
</div>
)}
</Fragment>
);
};
export default Item;
複制
必要 api 參考
- window/getSelection
- Selection/getRangeAt
- Range/selectNodeContents
原文參考
- hackernoon.com/copying-tex…