iT邦幫忙

2024 iThome 鐵人賽

DAY 23
1

每一次的複製都是一種選擇,是將資訊暫時保存並隨時調用的過程。這讓我聯想到學習中的每個知識點,就像複製到剪貼簿一樣,需要在關鍵時刻調用,而非僅僅收集或囤積。學習的目的不是簡單地記住,而是為了能夠隨時應用。這正是 useClipboard 的真正意義所在。
https://ithelp.ithome.com.tw/upload/images/20241006/201621150wRoTCIuOr.png

前言

useClipboard的主要功能是為應用程式提供複製到剪貼簿的功能,使文字內容的複製變得輕鬆直觀。這是蠻常見的需求。就讓我們逐步解析其原理和實現方式。

可以分為以下幾個部分:

  1. 內容複製操作
  2. 複製狀態管理
  3. 非同步處理
  4. 效能最佳化
  5. 錯誤處理及用戶提示

我們來逐一詳細解釋這些部分。

1. 內容複製操作

useClipboard 的核心功能是複製指定的內容到剪貼簿,這一操作依賴於 JavaScript 的 Clipboard API。通常,函式會使用 document.execCommand('copy') 或更現代的 navigator.clipboard.writeText() 來完成複製任務。

const copy = async (text: string) => {
  try {
    await navigator.clipboard.writeText(text);
    state.copied = true;
    state.error = null;
  } catch (err) {
    state.error = err;
    state.copied = false;
  }
}

這段程式碼是用來將文本內容寫入到剪貼簿中。它首先嘗試使用 navigator.clipboard.writeText() 這個現代的 API,如果成功則將 state.copied 設定為 true,表示複製成功,否則捕捉錯誤並更新 state.error

2. 複製狀態管理

useClipboard 通常會管理一些關鍵的狀態,比如:

  • copied:表示是否已成功複製內容。
  • error:表示複製過程中是否發生了錯誤。
  • timeoutId:用來管理狀態重置的計時器。
const state = reactive({
  copied: false,
  error: null,
  timeoutId: null
})

這些狀態允許外部組件跟踪複製的結果,可以根據 copied 的值來顯示提示訊息(如“已成功複製”)或錯誤訊息。

3. 非同步處理

在複製操作之後,通常會有一些非同步處理需求,例如提示用戶複製成功並在一段時間後重置狀態。這一過程可以使用 setTimeout 來控制。

if (options.timeout) {
  state.timeoutId = setTimeout(() => {
    state.copied = false;
  }, options.timeout);
}

這段程式碼用於設定一個超時,當複製成功後,過了一段時間(由 options.timeout 決定,例如 2000 毫秒),會將 state.copied 重置為 false,以便清除狀態並隨時準備下一次複製。

4. 效能最佳化

為了避免頻繁操作剪貼簿導致效能問題,通常會使用 throttledebounce 來限制操作頻率。可以通過對 copy 函式進行封裝,使得連續多次快速點擊時,只會在一定時間內觸發一次。

const throttledCopy = throttle(copy, 300);

這段程式碼能有效限制 copy 函式的執行頻率。在 300 毫秒內,即使多次觸發,也只會執行一次實際的複製操作。這樣的設計可以有效避免浪費效能。

5. 錯誤處理及用戶提示

考慮到不同瀏覽器對 Clipboard API 的支援程度不一,useClipboard 需要處理多種情況,並為用戶提供適當的反饋。例如,當用戶的瀏覽器不支援 Clipboard API 時,就必須退回去使用較老舊的 document.execCommand('copy') 方法來實現複製功能。

if (!navigator.clipboard) {
  try {
    const textArea = document.createElement("textarea");
    textArea.value = text;
    document.body.appendChild(textArea);
    textArea.select();
    document.execCommand("copy");
    document.body.removeChild(textArea);
    state.copied = true;
  } catch (err) {
    state.error = err;
  }
}

這段程式碼用於處理在不支持 navigator.clipboard 的情況下,通過創建一個隱藏的 textarea,手動選擇文本並執行 document.execCommand("copy") 來進行複製。

工作流程

  1. 用戶點擊按鈕或觸發複製行為時,useClipboard 將執行 copy 函式。
  2. 函式嘗試使用 Clipboard API 進行內容複製,並更新狀態(成功或錯誤)。
  3. 如果複製成功,根據設定的 timeout 設定計時器,在一段時間後重置狀態。
  4. 如果使用的瀏覽器不支持 Clipboard API,則降級使用 document.execCommand("copy") 進行複製。
  5. 在整個過程中,可以使用 throttle 來限制操作頻率,避免效能問題。

https://ithelp.ithome.com.tw/upload/images/20241006/20162115Epn8CDoX7E.png

原始碼部分解釋

1. 型別定義

export interface UseClipboardOptions {
  timeout?: number; // 複製狀態持續時間
}

這裡定義了用於設定複製行為的參數:

  • timeout:控制狀態保持『已複製』的時間,以毫秒為單位。

2. useClipboard 函式

export function useClipboard(options: UseClipboardOptions = {}) {
  const state = reactive({
    copied: false,
    error: null,
  });

  const copy = async (text: string) => {
    // 複製邏輯
  };

  return {
    copy,
    copied: computed(() => state.copied),
    error: computed(() => state.error),
  };
}

這是 useClipboard 的主要函式,它創建了一個響應式狀態 state,並返回 copy 函式,以及 copiederror 的計算屬性,方便外部組件使用和跟踪狀態。

總結

useClipboard 是一個簡單而實用的函式。它封裝了瀏覽器的 Clipboard API,提供統一的介面進行內容複製。這個函式不僅管理複製狀態和潛在錯誤,還處理了跨瀏覽器的相容性問題,讓開發者能輕鬆實現剪貼簿功能。

希望這份解析能幫助你更深入理解 useClipboard 的實作原理和使用方法。如有任何疑問或需要補充的地方,歡迎隨時提出!


上一篇
D-22 useClipboard 文件說明與範例
下一篇
D-24 useWebWorkerFn 文件說明與範例 - 忍術替身術
系列文
不會 VueUse 而被提分手的我30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言