А вот и API асинхронного буфера обмена

внешний интерфейс HTML

Если я спрошу: знаете ли вы «буфер обмена»?

Боюсь, никто не знает. Мы не знаем, сколько раз мы «копируем» и «вставляем» на наш компьютер или мобильный телефон каждый день. «Буфер обмена» используется после каждого «копирования» и «вставки».

Согласно Википедии:

The clipboard is a data buffer used for short-term data storage and/or data transfer between documents or applications used by cut, copy and paste operations and provided by the operating system.

переводить:

Буфер обмена — это кеш данных, используемый для хранения/передачи краткосрочных данных между документами или приложениями, который используется, когда пользователь выполняет операции вырезания, копирования и вставки, предусмотренные операционной системой.

Наиболее важным моментом здесь является то, что «буфер обмена» «предоставляется операционной системой», то есть это программная функция на системном уровне.

Для фронтенд-разработчиков, если я спрошу: знаете ли вы, как работать с «буфером обмена»?

Первой реакцией многих людей может быть: используйте clipboard.js...

Принцип работы clipboard.js

буфер обмена.js (clipboardjs.com/) имеет более 24 000 звезд на Github, и его популярность очевидна. Что касается использования этой библиотеки, вы можете убедиться сами.Здесь мы в основном анализируем принцип ее реализации, чтобы понять текущую основную технологию работы с буфером обмена.

Короче говоря, clipboard.js использует два существующих веб-API (первый принадлежит HTML5, а второй принадлежит API редактирования HTML):

  • HTMLInputElement.select()
  • document.execCommand()

Соответственно, принцип имеет всего два шага.

Первый шаг — создать временный элемент texterea, скрыть его с помощью CSS, затем назначить текст для копирования в текстовую область и выделить все в текстовой области:

// https://github.com/zenorocha/clipboard.js/blob/master/src/clipboard-action.js
/**
 * Creates a fake textarea element, sets its value from `text` property,
 * and makes a selection on it.
 */
// selectFake()
// 创建临时的texterea元素
this.fakeElem = document.createElement('textarea');
// 隐藏这个元素
this.fakeElem.style.position = 'absolute';
this.fakeElem.style[ isRTL ? 'right' : 'left' ] = '-9999px';
// 把要复制的文本赋给文本区并选择全部内容
this.fakeElem.value = this.text;
this.selectedText = select(this.fakeElem);
// 触发复制
this.copyText();

Второй шаг — запуск операции копирования через скрипт, в случае успеха текст будет записан в буфер обмена, а затем по результату выполнения будет отправлено пользовательское событие:

// https://github.com/zenorocha/clipboard.js/blob/master/src/clipboard-action.js
/**
 * Executes the copy operation based on the current selection.
 */
// copyText()
succeeded = document.execCommand(this.action);
this.handleResult(succeeded);

/**
  * Fires an event based on the copy operation result.
  * @param {Boolean} succeeded
  */
handleResult(succeeded) {
    this.emitter.emit(succeeded ? 'success' : 'error', {
        action: this.action,
        text: this.selectedText,
        trigger: this.trigger,
        clearSelection: this.clearSelection.bind(this)
    });
}

Как упоминалось ранее, буфер обмена предоставляется операционной системой и является общесистемным. Из соображений безопасности и удобства пользователей производители браузеров доверяют только операциям копирования, инициированным пользователями через приложения, документы или сценарии. Кроме того, источником содержимого, скопированного в буфер обмена, должен быть существующий элемент DOM.

Результатом описанной выше операции копирования является запись текстового содержимого в буфер обмена. Если вы хотите прочитать содержимое буфера обмена, вы должны зарегистрировать обработчик для операции события вставки и получить содержимое буфера обмена с помощью метода e.clipboardData.getData(). Это позволяет выполнять некоторую предварительную обработку содержимого буфера обмена перед тем, как пользователь вставит содержимое в целевое поле ввода. Но не в этом суть данной статьи.

Хотя метод, используемый clipboard.js, поддерживается почти всеми браузерами, он имеет много недостатков.

Недостатки предшествующего уровня техники

Что не так с предыдущей технологией? В дополнение к предыдущей необходимости программно моделировать инициируемую пользователем операцию копирования буфера обмена с помощью execCommand, есть:

  • Первоначальное назначение execCommand — редактировать DOM, и между реализациями браузера есть много различий.
  • Операция копирования-вставки является синхронной и блокирует основной поток, в результате чего страница не отвечает.
  • Если вы потом выскочите окно для подачи заявки на авторизацию, вы можете раздражать пользователя
  • Соответственно, предотвратить безвредную обработку или перекодирование определенных типов данных, таких как изображения.
  • Во избежание внешнего использования иногда необходима транскодировка

Чтобы преодолеть эти проблемы, W3C начал разрабатывать соответствующие стандарты: API буфера обмена и события (Woohoo.I 3.org/TR/клип кабан…).

API буфера обмена и события определяют API асинхронного буфера обмена, который соответствующим образом добавляет событие clipboardchange.

Async Clipboard API

Другими словами, чтобы избежать блокировки основного потока, этот новый стандарт вводит API асинхронного буфера обмена на основе Promise. Поскольку буфер обмена является программной функцией системного уровня, в навигаторе монтируется соответствующий API:

navigator.clipboard

Объект буфера обмена имеет 4 метода:

Promise<DataTransfer> read();
Promise<DOMString> readText();
Promise<void> write(DataTransfer data);
Promise<void> writeText(DOMString data);

Два буфера обмена для чтения, два буфера обмена для записи.

Для чтения и записи поддерживаются следующие типы данных:

  • text/plain
  • text/uri-list
  • text/csv
  • text/css
  • text/html
  • application/xhtml+xml
  • image/png
  • image/jpg, image/jpeg
  • image/gif
  • image/svg+xml
  • application/xml, text/xml
  • application/javascript
  • application/json
  • application/octet-stream

read()

navigator.clipboard.read().then(function(data) {
  for (var i = 0; i < data.items.length; i++) {
    if (data.items[i].type == "text/plain") {
      console.log("Your string: ", data.items[i].getAs("text/plain"));
    } else {
      console.error("No text/plain data on clipboard.");
    }
  }
});

readText()

navigator.clipboard.readText().then(function(data) {
  console.log("Your string: ", data);
});

write(data)

var data = new DataTransfer();
data.items.add("text/plain", "Howdy, partner!");
navigator.clipboard.write(data).then(function() {
  console.log("Copied to clipboard successfully!");
}, function() {
  console.error("Unable to write to clipboard. :-(");
});

writeText(data)

navigator.clipboard.writeText("Howdy, partner!").then(function() {
  console.log("Copied to clipboard successfully!");
}, function() {
  console.error("Unable to write to clipboard. :-(");
});

Меры предосторожности

  1. navigator.clipboard можно использовать только в «контексте безопасности». Что такое «контекст безопасности»? Проще говоря, он находится в среде localhost и HTTPS. (Доступно через свойство window.isSecureContext.)
  2. В настоящее время в настольных браузерах поддерживаются только Chrome, Firefox и Opera, Safari и IE/Edge пока не поддерживаются, кроме того, Chrome поддерживает только readText() и writeText().

Ссылка на ссылку: