運用 DataTransfer API 打破藩籬

讓使用者可以在瀏覽器視窗外分享資料。

您可能聽過 DataTransfer API, 部分 HTML5 拖曳 API剪貼簿事件。這項服務可以 用於在來源和接收目標之間轉移資料。

瀏覽器支援

  • Chrome:3.
  • Edge:12.
  • Firefox:3.5。
  • Safari:4.

資料來源

拖曳與複製貼上互動常用於網頁內的互動 將簡單的文字從 A 轉移到 B然而,往往受到忽略 這類互動不會超出瀏覽器視窗

瀏覽器內建的拖曳和複製貼上互動功能 與任何來源無關聯。這個 API 支援 根據資料移轉至何處,有不同行為的資料項目。您的 網頁應用程式可在監聽傳入事件時,傳送及接收轉移的資料。

這項功能可以改變我們對網路分享和互通性的看法 安裝新的應用程式不必仰賴在應用程式之間轉移資料 但不再是與緊密結合的整合功能您可以改為讓使用者擁有完整的轉移控制權 將資料傳輸至所在位置

DataTransfer API 可進行的互動範例。(影片不包含音效)。

轉移資料

首先,請導入拖曳或複製貼上功能。範例 下方顯示的是拖曳互動 但複製貼上的程序與上述做法類似如果 如果您不熟悉 Drag and Drop API,我們有這篇實用文章 參閱 HTML5 拖曳功能簡介,瞭解相關細節。

您可以透過提供 MIME 類型鍵資料, 就能自由與外部應用程式互動 大部分的 WYSIWYG 編輯器、文字編輯器和瀏覽器都回應「基本」中所使用的 MIME 類型 範例。

document.querySelector('#dragSource')
.addEventListener('dragstart', (event) => {
  event.dataTransfer.setData('text/plain', 'Foo bar');
  event.dataTransfer.setData('text/html', '<h1>Foo bar</h1>');
  event.dataTransfer.setData('text/uri-list', 'https://example.com');
});

請注意 event.dataTransfer 屬性。這會傳回 DataTransfer。阿斯 您就會看到這個物件,有時會由具有其他名稱的屬性傳回。

接收資料移轉作業的方式與提供資料幾乎相同。監聽接收事件 (droppaste) 並讀取索引鍵。拖曳元素時,瀏覽器僅可存取 對應至資料的 type 鍵。只有在掉落後才能存取資料本身。

document.querySelector('#dropTarget')
.addEventListener('dragover', (event) => {
  console.log(event.dataTransfer.types);
  // Without this, the drop event won't fire.
  event.preventDefault();
});

document.querySelector('#dropTarget')
.addEventListener('drop', (event) => {
  // Log all the transferred data items to the console.
  for (let type of event.dataTransfer.types) {
    console.log({ type, data: event.dataTransfer.getData(type) });
  }
  event.preventDefault();
});

應用程式廣泛支援三種 MIME 類型:

  • text/htmlcontentEditable 元素中顯示 HTML 酬載 文字 (WYSIWYG) 編輯器,例如 Google 文件、Microsoft Word 等等。
  • text/plain: 設定輸入元素、程式碼編輯器的內容和備用值的值 最低時間:text/html
  • text/uri-list在網址列或瀏覽器頁面中,前往網址。網址 捷徑會在拖放目錄或桌面時建立。

所見即所得,所見即所得,WYSIWYG 編輯器廣泛採用 text/html 時非常實用。如同 HTML 中的一樣 就可以嵌入 資料網址或公開 可存取的網址這項功能適合將影像內容 (例如畫布) 匯出至編輯者,例如 Google 文件

const redPixel = 'data:image/gif;base64,R0lGODdhAQABAPAAAP8AAAAAACwAAAAAAQABAAACAkQBADs=';
const html = '<img src="' + redPixel + '" width="100" height="100" alt="" />';
event.dataTransfer.setData('text/html', html);

使用複製及貼上功能轉移

使用 DataTransfer API 搭配複製貼上互動的方式如下。請注意 DataTransfer 物件是由名為 clipboardData 的屬性傳回,用於剪貼簿事件。

// Listen to copy-paste events on the document.
document.addEventListener('copy', (event) => {
  const copySource = document.querySelector('#copySource');
  // Only copy when the `activeElement` (i.e., focused element) is,
  // or is within, the `copySource` element.
  if (copySource.contains(document.activeElement)) {
    event.clipboardData.setData('text/plain', 'Foo bar');
    event.preventDefault();
  }
});

document.addEventListener('paste', (event) => {
  const pasteTarget = document.querySelector('#pasteTarget');
  if (pasteTarget.contains(document.activeElement)) {
    const data = event.clipboardData.getData('text/plain');
    console.log(data);
  }
});

自訂資料格式

您不必受限於原始 MIME 類型,但可以使用任何金鑰識別已傳輸的資料 資料。如要在應用程式中進行跨瀏覽器互動,這項功能非常實用。如下所示 可以透過 JSON.stringify()JSON.parse() 函式轉移更複雜的資料。

document.querySelector('#dragSource')
.addEventListener('dragstart', (event) => {
  const data = { foo: 'bar' };
  event.dataTransfer.setData('my-custom-type', JSON.stringify(data));
});

document.querySelector('#dropTarget')
.addEventListener('dragover', (event) => {
  // Only allow dropping when our custom data is available.
  if (event.dataTransfer.types.includes('my-custom-type')) {
    event.preventDefault();
  }
});

document.querySelector('#dropTarget')
.addEventListener('drop', (event) => {
  if (event.dataTransfer.types.includes('my-custom-type')) {
    event.preventDefault();
    const dataString = event.dataTransfer.getData('my-custom-type');
    const data = JSON.parse(dataString);
    console.log(data);
  }
});

連線至網路

雖然自訂格式非常適合由您控管的應用程式相互通訊, 也可以限制使用者在將資料轉移至未使用您格式的應用程式時。如果您想 連結網路上的第三方應用程式,您需要使用通用資料格式。

JSON-LD (連結資料) 標準是不錯的選擇。是 輕而易舉在 JavaScript 中讀取及寫入。Schema.org 包含 您也可以選擇使用自訂結構定義。

const data = {
  '@context': 'https://schema.org',
  '@type': 'ImageObject',
  contentLocation: 'Venice, Italy',
  contentUrl: 'venice.jpg',
  datePublished: '2010-08-08',
  description: 'I took this picture during our honey moon.',
  name: 'Canal in Venice',
};
event.dataTransfer.setData('application/ld+json', JSON.stringify(data));

使用 Schema.org 類型時,您可以先從一般 Thing 類型著手。 或使用更靠近用途的工具,例如活動人物MediaObjectPlace 或高度特定類型,例如 MedicalEntity。使用 TypeScript 時,您可以使用 schema-dts 類型定義的介面定義。

透過傳輸及接收 JSON-LD 資料,您可以支援更具連結且開放的網路環境。取代為 實作相同語言的應用程式,可與外部人員深入整合 應用程式。不需要進行複雜的 API 整合。所有所需資訊 包含在轉移資料中

您可以試想如何在任何 (網頁) 應用程式之間轉移資料, 限制:將日曆活動中的活動分享到喜愛的「待辦事項」應用程式、 管理電子郵件、分享聯絡人。這樣應該很棒,對吧?這一切都從您開始!🙌

疑慮

DataTransfer API 現已開放使用,但在整合前有一些注意事項。

瀏覽器相容性

電腦版瀏覽器都提供上述技術的完整支援,而行動裝置則支援 而不是這項技術已在所有主要瀏覽器 (Chrome、Edge、Firefox、Safari) 和 或是作業系統 (Android、ChromeOS、iOS、macOS、Ubuntu Linux 和 Windows),但遺憾的是 Android 和 iOS 均未通過測試雖然瀏覽器持續開發,但目前技術有限 僅適用於電腦版瀏覽器

爭取曝光機會

拖曳和複製貼上是系統層級的操作,用於桌上型電腦 都來自 40 多年前的第一屆統一發票。回想一下 來整理檔案網路上還有少許這種狀況。

你必須向使用者說明這項全新的互動方式,並想出使用者體驗模式, 尤其是那些對行動裝置不方便使用電腦的使用者,更是如此。

無障礙設定

拖曳方法並不容易存取,但 DataTransfer API 也可以支援複製貼上。 請務必監聽複製貼上事件。不必多費工夫 感謝新增這項資訊

安全性和隱私權

使用這項技巧時,請留意幾個安全性和隱私權注意事項。

  • 使用者裝置上的其他應用程式可以存取剪貼簿資料。
  • 您拖曳的網頁應用程式可以存取類型鍵,而非資料。僅有資料 可在放置或貼上時使用
  • 收到的資料應視為其他使用者輸入內容。請先清理及驗證資料,再使用

開始使用 Transmat 輔助程式庫

您有興趣在應用程式中使用 DataTransfer API 嗎?歡迎參閱 GitHub 上的 Transmat 程式庫。這個開放原始碼程式庫可讓瀏覽器 其中提供 JSON-LD 公用程式,其中包含可回應 醒目顯示放置區域,並讓您可以整合現有拖曳項目間的資料移轉作業 。

import { Transmat, TransmatObserver, addListeners } from 'transmat';

// Send data on drag/copy.
addListeners(myElement, 'transmit', (event) => {
  const transmat = new Transmat(event);
  transmat.setData({
    'text/plain': 'Foobar',
    'application/json': { foo: 'bar' },
  });
});

// Receive data on drop/paste.
addListeners(myElement, 'receive', (event) => {
  const transmat = new Transmat(event);
  if (transmat.hasType('application/json') && transmat.accept()) {
    const data = JSON.parse(transmat.getData('application/json'));
  }
});

// Observe transfer events and highlight drop areas.
const obs = new TransmatObserver((entries) => {
  for (const entry of entries) {
    const transmat = new Transmat(entry.event);
    if (transmat.hasMimeType('application/json')) {
      entry.target.classList.toggle('drag-over', entry.isTarget);
      entry.target.classList.toggle('drag-active', entry.isActive);
    }
  }
});
obs.observe(myElement);

特別銘謝

主頁橫幅由 Luba Ertel 提供 Unsplash