Рейтинг:2

Как правильно определить библиотеку, чтобы JS выполнялся после выполнения определенного условия?

флаг cn

Я создаю собственный модуль для выполнения некоторого JS ПОСЛЕ очистки кеша. Вот структура модуля:

Модуль -> flush.info.yml

Название: Флеш
тип: модуль
описание: Очень важный модуль.
пакет: Пользовательский
версия: 1.0
core_version_requirement: ^8 || ^9

Модуль -> flush.libraries.yml

румянец:
  версия: 1.х
  js:
    js/flush.js: {}
  зависимости:
    - ядро/jquery
    - настройки ядра/друпала

Модуль -> флеш.модуль

<?php

используйте Drupal\Core\Form\FormStateInterface;

/**
 * Реализация hook_cache_flush()
 */

  функция flush_cache_flush() {
    \Drupal::state()->set('flush_cache_cleared', TRUE);
  }

  функция flush_page_attachments (массив и $ вложения) {
    если (\Drupal::state()->get('flush_cache_cleared')) {
      $attachments['#attached']['library'][] = 'flush/flush';
     \Drupal::state()->set('flush_cache_cleared', FALSE);
    }
  }

Модуль -> JS -> flush.js

(функция ($, Drupal, drupalSettings) {
    'использовать строгий';

    Drupal.behaviors.flush = {
      /**
       * Поведение присоединения Drupal.
       */
      прикрепить: функция (контекст, настройки) {
        this.settings = this.getSettings (настройки);
        Сообщить("Смыть!");
        console.log("Привет, мир");
      },
    };
  })(jQuery, Drupal, drupalSettings);

Обе функции в flush.module работают правильно, однако JS с #attached, который просто должен использовать alert(), никогда не запускается. Я считаю, что проблема связана именно с этой строкой: $attachments['#attached']['library'][] = 'flush/flush';

Есть ли что-то очевидное, что я делаю неправильно? Я использовал page_attachments в качестве метода для прикрепления JS, потому что он не обязательно должен быть связан с определенной частью страницы или массивом рендеринга и т. д. Пожалуйста, дайте мне знать, если у вас есть какие-либо потенциальные идеи относительно того, в чем может быть проблема. быть, спасибо!

sonfd avatar
флаг in
Что произойдет, если вы запустите его без оператора if в hook_page_attachments?
Joseph avatar
флаг cn
@sonfd JS все еще не работает. Я знаю, что оператор if срабатывает, как и предполагалось, потому что, если я повторяю команду JS alert() внутри него, он срабатывает. Только когда я пытаюсь подключить JS через библиотеку, ничего не происходит.
Jaypan avatar
флаг de
Вы очищали кеш после добавления этого кода?
Joseph avatar
флаг cn
@Jaypan Да, очистка кеша работает, и если я добавлю JS в функцию flush_page_attachments(), она будет работать так, как предполагалось (т.е. предупреждение, когда кеш очищается), однако использование библиотеки, которая является правильным способом сделать это, не работает .
флаг fr
Вполне допустимо прикрепить библиотеку внутри hook_page_attachments(), как вы пытаетесь сделать - у меня есть рабочий код, который делает это. Я не вижу ничего плохого в вашем hook_page_attachments(). НО, если вы добавили или изменили flush.libraries.yml после того, как включили свой флеш-модуль, то новый файл библиотек может не получиться. Попробуйте удалить и заново установить модуль.
Jaypan avatar
флаг de
Это было моей точкой зрения.
Joseph avatar
флаг cn
Очистка кеша не заставляет мою библиотеку работать, равно как и удаление и переустановка пользовательского модуля.Когда я добавляю JS в hook_page_attachments() (например, предупреждение), кажется, что он появляется после очистки кеша, но до перезагрузки страницы. Может быть, поэтому прикрепленный JS через библиотеку не появляется? Я чувствую, что он все еще должен вызывать предупреждение, как если бы он был добавлен непосредственно в hook_page_attachments(). Хотя не уверен.
apaderno avatar
флаг us
Вы уверены, что редактируете правильный файл? Вы проверили, что модуль не скопирован в два разных каталога?
apaderno avatar
флаг us
Присоединение кода JavaScript в качестве библиотеки — это то, что делает ядро ​​Drupal. Он даже использует тот же крючок, что и вы. Если что-то не так, это не используемый крючок. См. [`contextual_page_attachments()`](https://api.drupal.org/api/drupal/core%21modules%21contextual%21contextual.module/function/contextual_page_attachments/9.3.x) в качестве примера того, что делает ядро ​​Drupal. IMO, если бы правильным способом добавления кода JavaScript было добавление блока, ядро ​​Drupal сделало бы это.
apaderno avatar
флаг us
См. также содержимое [contextual.libraries.yml](https://api.drupal.org/api/drupal/core%21modules%21contextual%21contextual.libraries.yml/9.3.x), из которого видно, что Библиотека *drupal.contextual-links* содержит код JavaScript.
sonfd avatar
флаг in
Я думаю, вам просто нужно более полное определение того, что означает «после очистки кеша». Является ли это абсолютной правдой для вселенной на момент очистки кэша? Должен ли пользователь быть на сайте до того, как кеш будет очищен, чтобы это имело значение? Это период времени, который длится X секунд после очистки кеша?
sonfd avatar
флаг in
То, как вы пытаетесь использовать состояние, не сработает. Ваш js будет прикреплен только буквально к запросу одной страницы от одного человека во вселенной после очистки кеша.
apaderno avatar
флаг us
@sonfd Код можно изменить, чтобы добавить библиотеку к первым запросам X-страницы, выполняемым после очистки кеша. Я не понимаю, почему он был добавлен после очистки кеша. Вероятно, просмотр того, какой код JavaScript прикреплен и почему, поможет дать лучший ответ.
Рейтинг:2
флаг cn

Я бы не стал использовать Drupal::state() или hook_page_attachments(), они слишком статичны. Лучше использовать значение сеанса и блок, см. мой комментарий в предыдущем вопросе.

Установите значение сеанса в хуке при очистке кеша и только в том случае, если он не запущен из командной строки:

функция flush_cache_flush() {
  если (PHP_SAPI !== 'cli') {
    \Drupal::request()->getSession()->set('run_flush_js', TRUE);
  }
}

В блоке проверьте значение сеанса и удалите его, чтобы он не сохранялся после перенаправления.

src/Плагин/Блок/FlushBlock.php

<?php

пространство имен Drupal\flush\Plugin\Block;

используйте Drupal\Core\Block\BlockBase;

/**
 * Обеспечивает флеш-блок.
 *
 * @Блокировать(
 * id = "flush_flush",
 * admin_label = @Translation("Сброс"),
 * категория = @Translation("Пользовательский")
 * )
 */
класс FlushBlock расширяет BlockBase {

  /**
   * {@inheritdoc}
   */
  общедоступная функция сборки () {
    $session = \Drupal::request()->getSession();  
    $сборка = [];
    если ($session->get('run_flush_js')) {
      $session->remove('run_flush_js');
      $сборка['контент'] = [
        '#markup' => '<div class="run-flush-js"></div>',
        '#attached' => ['library' => ['flush/flush']],
      ];
    }
    $build['#cache']['max-age'] = 0;
    вернуть $сборку;
  }
}

js/flush.js

(функция ($, Drupal, один раз) {
  'использовать строгий';

  Drupal.behaviors.flush = {
    /**
     * Поведение присоединения Drupal.
     */
    прикрепить: функция (контекст, настройки) {
      if (once('flush', '.run-flush-js', context).length) {
        Сообщить("Смыть!");
      }
    }
  };
})(jQuery, Drupal, один раз);

флеш.libraries.yml

румянец:
  js:
    js/flush.js: {}
  зависимости:
    - ядро/друпал
    - ядро/jquery
    - ядро/один раз

Изменить: обновить код js, см. Как я могу заставить этот код JavaScript выполняться, когда модуль BigPipe включен?

apaderno avatar
флаг us
`hook_page_attachments()` используется для условного добавления вложений на страницу до ее отображения, а API состояния используется для хранения значений состояния сайта. ОП не делает ничего плохого в их использовании. Предлагаемый вариант имеет свои недостатки: значение сеанса указано для каждого пользователя, и необходимо добавить блок в область темы (что также означает, что изменение темы может привести к тому, что библиотека не будет добавлена).
apaderno avatar
флаг us
Затем использование блока и значения сеанса не решит проблему, которую замечает OP. Это может быть OP, редактировавший файл .libraries.yml после установки модуля, или OP редактирующий неправильный файл .libraries.yml (что также может произойти, потому что есть две копии одного и того же модуля); в обоих случаях изменение способа добавления библиотеки на страницу не решает реальной проблемы.
4uk4 avatar
флаг cn
Я думаю, вам нужна сессия, без запуска javascript на случайном клиенте, который запрашивает первую страницу после очистки кеша. Есть и другие способы, кроме блока, но это, вероятно, самый быстрый способ, потому что вы можете использовать систему того, как Drupal отображает страницы. Это работает даже с BipPipe. Я тестировал его с и без, и вы можете видеть, как это влияет на загрузку страницы.
apaderno avatar
флаг us
ОП не сказал, что хочет запустить код JavaScript для того же пользователя, который вызвал очистку кеша; в этом случае, однако, использование значения сеанса не обязательно, так как пользователь, вызвавший очистку кеша, посещал как минимум две разные страницы или одну и ту же страницу дважды. Даже если предположить, что OP хочет добавить код JavaScript на страницу, запрошенную пользователем, который вызвал очистку кеша (что не имеет смысла, поскольку кеш очищается для каждого пользователя), было бы достаточно сохранить идентификатор пользователя с помощью API состояния.
apaderno avatar
флаг us
Это имеет смысл, потому что пользователь, который вошел в систему, когда кеш был очищен, является значением состояния для сайта, а не значением сеанса.
Рейтинг:1
флаг in

Я думаю, что вы должны подойти к этому по-другому. Вот что я бы сделал:

Во-первых, реализуйте hook_cache_flush() и используйте его для сохранения времени последней очистки кеша в состояние Drupal.

функция flush_cache_flush() {
  \Drupal::state()->set('flush_cache_cleared', time());
}

Затем используйте hook_page_attachments(), чтобы всегда прикреплять свой javascript на каждой странице, но передавать отметку времени очистки кеша вашему javascript.

функция flush_page_attachments (массив и $ вложения) {
  $attachments['#attached']['library'][] = 'flush/flush';
  $attachments['#attached']['drupalSettings']['flush_cache_cleared'] = \Drupal::state()->get('flush_cache_cleared');
}

Наконец, в вашем javascript проверьте, является ли новое время очистки кеша более новым, чем предыдущее (вам нужно будет сохранить это на стороне клиента через локальное хранилище или что-то в этом роде).

Если время отличается, вы знаете, что кеш был очищен.

(функция ($, Drupal, drupalSettings) {
  'использовать строгий';

  Drupal.behaviors.flush = {
    прикрепить: функция (контекст, настройки) {

      let cacheFlushedTime = drupalSettings['flush_cache_cleared'];
      // Делаем здесь что-то с cache_flushed_time, например
      // сравниваем его с ранее известным временем очистки кеша...

    },
  };
})(jQuery, Drupal, drupalSettings);

Ответить или комментировать

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