Как можно активировать работу буфера обмена после выполнения асинхронного вызова в браузере Safari при использовании фреймворка Vue?

Почему в приложении на Vue.js не работает копирование в буфер обмена после асинхронного вызова, в то время как на нативном JavaScript все работает как надо?
  • 8 февраля 2024 г. 12:08
Ответы на вопрос 1
Проблема с копированием в буфер обмена после асинхронного вызова во Vue.js, как и в любом другом фреймворке (и даже в чистом JavaScript), обычно связана с тем, что браузеры разрешают доступ к буферу обмена в рамках обработчиков событий, вызванных действиями пользователя (например, клик мышью). После завершения асинхронной операции контекст, в котором выполняется доступ к буферу обмена, не всегда считается "живым" (live), как это бывает при непосредственном обработчике события.

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

Давайте рассмотрим, как можно это реализовать:

Метод 1: Использование `execCommand('copy')` в обработчике событий, вызванных пользователем

Этот метод реализует копирование в буфер обмена, как часть обратного вызова события клика:

```html
<button @click="copyToClipboard">Copy</button>
```

```javascript
methods: {
  async fetchSomeData() {
    // Представим, что здесь асинхронный запрос к API
    let data = await fetch('/some-api-endpoint');
    data = await data.text();

    // Хранение данных в состоянии Vue для дальнейшего использования
    this.dataToCopy = data;
  },
  copyToClipboard() {
    // Предварительно получаем данные (например, из API)
    this.fetchSomeData().then(() => {
      // Создание временного элемента textarea для копирования текста
      const textarea = document.createElement('textarea');
      textarea.style.position = 'fixed';  
      textarea.style.opacity = '0';
      textarea.value = this.dataToCopy;

      document.body.appendChild(textarea);
      textarea.select();

      try {
        document.execCommand('copy');
        console.log('Содержимое скопировано в буфер обмена.');
      } catch (err) {
        console.error('Не удалось скопировать содержимое: ', err);
      }

      document.body.removeChild(textarea);
    });
  }
}
```

Важно заметить, что `document.execCommand('copy')` считается устаревшей и может не поддерживаться в будущих версиях браузеров. Поэтому предпочтительнее использовать современные API, например, Clipboard API.

Метод 2: Использование Clipboard API

Clipboard API предоставляет более современный и мощный способ взаимодействия с буфером обмена.

```html
<button @click="copyToClipboard">Copy</button>
```

```javascript
methods: {
  async fetchSomeData() {
    // Представим, что здесь асинхронный запрос к API
    const data = await fetch('/some-api-endpoint');
    this.dataToCopy = await data.text();
  },
  copyToClipboard() {
    // Предварительно получаем данные
    this.fetchSomeData().then(() => {
      if (navigator.clipboard && window.isSecureContext) {
        // Использование Clipboard API для копирования текста
        navigator.clipboard.writeText(this.dataToCopy).then(function() {
          console.log('Содержимое скопировано в буфер обмена.');
        }, function(err) {
          console.error('Не удалось скопировать содержимое: ', err);
        });
      } else {
        // Запасной план: document.execCommand или другие методы
Похожие вопросы