一、前言
使用者在瀏覽網頁的過程中,執行復制操作的場景是非常多的,例如:複製連結地址、複製分享文案等等。
而前端通過模擬使用者的複製操作,可以減少操作的步驟,進而優化使用者體驗。
複製操作主要分為以下兩部分:
- 選中文字:對應使用者通過滑鼠或者觸屏選中文字的操作。
- 作業系統剪貼簿:對應使用者按下 Ctrl(command) + C 的操作。
二、選中文字
首先,讀者需要明白,不是所有的文字都可以被選中的(後續會提到),筆者這裡先介紹幾個可以選中文字的情況:
1、input 和 textarea
由於 input 元素的工作方式因其型別屬性的值而有很大的差異,所以這裡只討論 text 的情況。
因為 JavaScript 提供了 HTTMLInputElement.select() 方法,所以選中 textarea 和 input 中的內容就變得非常簡單:
document.querySelector('input').select()
複製程式碼
如果 input 和 textarea 元素附加了 disabled 屬性,那麼其內容是無法被選中的,這種情況最好是將 disabled 替換為 readonly 。
2、div
div 元素並沒有開箱即用的 select() 方法,這就需要讀者瞭解一個新的物件: Selection 。
Selection 物件表示使用者選擇文字的範圍以及游標的範圍。關於 Selection 物件,讀者需要了解以下幾個術語:
- 錨點:選區的起始點。
- 焦點:選區的終止點。
- 範圍:文件中連續的一部分。
與 Selection 物件息息相關的還有一個 Range 物件,它主要用來自定義選區。對於這兩個物件不瞭解的讀者,可以檢視文末給出的參考文獻,接下來,利用 Selection 和 Range 物件實現上述 select() 方法:
function select (element) {
const selection = window.getSelection()
const range = document.createRange()
range.selectNodeContents(element)
selection.removeAllRanges()
selection.addRange(range)
}
複製程式碼
三、作業系統剪貼簿
document 暴露的 execCommand 方法,可以用來執行作業系統提供的命令,並且這些命令大部分作用於 Selection 物件。
該方法返回的布林值表示操作是否被支援或者是否被啟用,但是呼叫一個命令之前,不能嘗試使用返回值去校驗瀏覽器的相容性。
function copyText () {
let success = true
try {
success = document.execCommand('copy')
} catch (e) {
success = false
}
return success
}
複製程式碼
通過 execCommand 執行 copy 命令,可以將上述選中的文字新增到系統剪貼簿中,接下來使用者只需要在使用的地方按下 Ctrl(command) + V 即可貼上該內容。
四、特殊情況的處理
上述方案基本上可以應對大部分的情況,但是在 HTML 中,部分元素中的文字是無法被選中的,例如:
<select id="js-select">
<option value="apple">apple</option>
<option value="banana">banana</option>
<option value="peach">peach</option>
</select>
複製程式碼
既然 select 元素中的文字無法被選中,那麼就無法呼叫 execCommand 方法,又何談模擬使用者複製該文字呢?
這裡就需要採用以下套路:
1、獲取需要複製的文字
首先獲取到需要複製的文字內容,對於 select 元素,其文字內容可以根據 value 屬性獲取:
const element = document.getElementById('js-select')
const text = element.value
複製程式碼
2、建立透明元素
前面提到的 input、textarea 等元素都是可以被選中的,所以這裡筆者選擇建立一個透明的 textarea 來實現接下來的功能:
function createFakerElement (text) {
const fakerElement = document.createElement('textarea')
fakerElement.style.position = 'absolute'
fakerElement.style.left = '-9999px'
fakerElement.value = text
document.body.appendChild(fakerElement)
return fakerElement
}
複製程式碼
3、選中文字
前面也提到選中文字有兩種方式:
- 對於 input、textarea 元素,可以直接呼叫其 select 方法。
- 對於大多數元素(input 和 textarea 元素就是特例之一),可以通過 Selection 和 Range 完成選中文字的操作。
由於上述建立的是 textarea,這裡直接呼叫 select 方法:
function selectInput (element) {
return element.select()
}
複製程式碼
4、作業系統剪貼簿
前文已經提及,這裡不再贅述。
接下來只要按照順序執行這些操作即可:
document.getElementById('js-button').addEventListener('click', () => {
const element = document.getElementById('js-select')
// 1、獲取需要的文字內容
const text = element.value
// 2、建立透明的 textarea 元素
const fakerElement = createFakerElement(text)
// 3、選中相應的文字
selectInput(fakerElement)
// 4、執行作業系統剪貼簿的 copy 命令
const success = copyText()
if (success) {
console.log('複製成功')
} else {
console.log('複製失敗')
}
document.body.removeChild(fakerElement)
}, false)
複製程式碼
五、總結
由上文可知,前端模擬使用者的複製操作主要涉及兩方面的知識:
- 利用 Selection 和 Range 物件完成文字選中操作,比較特殊的是 input 和 textarea 元素自帶 select 方法實現該操作。
- 通過 document.execCommand 方法呼叫 copy 命令將內容儲存到系統剪貼簿中。
其中 document.execCommand 方法主要作用於 Selection 物件,所以當元素無法被選中時,該複製命令則無法達到預期的效果。
前面也到了 disabled 屬性以及 select 元素這樣的特例,相比較下,通過建立一個透明的 textarea 來模擬複製操作的方案可用性更高。
參考文獻
相關文章推薦
寫在最後
如果本文對您有幫助,點個贊吧!也歡迎小夥伴們關注我的訂閱號 漫談大前端