Puncte:2

Cum definesc corect o bibliotecă, astfel încât JS să se execute după ce o anumită condiție este îndeplinită?

drapel cn

Creez un modul personalizat pentru a executa niște JS DUPĂ ștergerea memoriei cache. Iată structura modulului:

Modul -> flush.info.yml

nume: Flush
tip: modul
descriere: Un modul foarte important.
pachet: Personalizat
versiune: 1.0
cerinta_versiune_core: ^8 || ^9

Modul -> flush.libraries.yml

culoare:
  versiunea: 1.x
  js:
    js/flush.js: {}
  dependențe:
    - core/jquery
    - core/drupalSettings

Modul -> flush.module

<?php

utilizați Drupal\Core\Form\FormStateInterface;

/**
 * Implementarea hook_cache_flush()
 */

  funcția flush_cache_flush() {
    \Drupal::state()->set('flush_cache_cleared', TRUE);
  }

  funcția flush_page_attachments(array &$attachments) {
    if (\Drupal::state()->get('flush_cache_cleared')) {
      $attachments['#attached']['library'][] = 'spașare/încărcare';
     \Drupal::state()->set('flush_cache_cleared', FALSE);
    }
  }

Modul -> JS -> flush.js

(funcție ($, Drupal, drupalSettings) {
    „utilizați strict”;

    Drupal.behaviors.flush = {
      /**
       * Comportamentul de ataşare Drupal.
       */
      atașați: funcție (context, setări) {
        this.settings = this.getSettings(setari);
        alert("bush!");
        console.log („Bună ziua, lume”);
      },
    };
  })(jQuery, Drupal, drupalSettings);

Ambele funcții din flush.module funcționează corect, totuși JS-ul care este # atașat și care pur și simplu ar trebui să folosească un alert() nu rulează niciodată. Cred că problema este legată în special de această linie: $attachments['#attached']['library'][] = 'spașare/încărcare';

Este ceva evident că fac greșit? Am folosit page_attachments ca metodă de atașare a JS, deoarece nu trebuie neapărat asociat cu o anumită parte a paginii sau cu o matrice de randare etc. Vă rugăm să-mi spuneți dacă aveți idei potențiale cu privire la problema. fii, multumesc!

sonfd avatar
drapel in
Ce se întâmplă dacă îl rulați fără instrucțiunea if din hook_page_attachments?
Joseph avatar
drapel cn
@sonfd JS încă nu funcționează. Știu că instrucțiunea if se declanșează așa cum este intenționat, deoarece dacă repetă comanda JS alert() în interiorul acesteia, se declanșează. Nu se întâmplă nimic decât atunci când încerc să atașez JS-ul prin bibliotecă.
Jaypan avatar
drapel de
Ai șters memoria cache după ce ai adăugat acel cod?
Joseph avatar
drapel cn
@Jaypan Da, ștergerea cache-ului funcționează și dacă adaug JS în funcția flush_page_attachments() va funcționa conform intenției (adică o alertă când memoria cache este șters), totuși, folosind o bibliotecă care este modalitatea corectă de a face acest lucru, nu funcționează .
drapel fr
Este perfect valid să atașați o bibliotecă în hook_page_attachments() așa cum încercați să faceți - am cod de lucru care face asta. Nu văd nimic în neregulă cu hook_page_attachments(). DAR dacă ați adăugat sau schimbat flush.libraries.yml după ce v-ați activat modulul de spălare, atunci este posibil ca noul fișier de biblioteci să nu fie preluat. Încercați să dezinstalați și să reinstalați modulul.
Jaypan avatar
drapel de
Acesta a fost punctul meu de vedere.
Joseph avatar
drapel cn
Ștergerea memoriei cache nu face ca biblioteca mea să funcționeze, nici dezinstalarea și reinstalarea modulului personalizat.Când adaug JS la hook_page_attachments() (ca o alertă) pare să apară după golirea memoriei cache, dar înainte ca pagina să se reîncarce. Acesta ar putea fi motivul pentru care JS atașat prin bibliotecă nu apare? Simt că ar trebui să declanșeze o alertă, așa cum o face atunci când este adăugată direct în hook_page_attachments(). Nu sunt sigur însă.
apaderno avatar
drapel us
Sunteți sigur că editați fișierul corect? Ai verificat că modulul nu este copiat în două directoare diferite?
apaderno avatar
drapel us
Atașarea codului JavaScript ca bibliotecă este ceea ce face core Drupal. Folosește chiar același cârlig pe care îl folosești. Dacă este ceva în neregulă, acesta nu este cârligul folosit. Vedeți [`contextual_page_attachments()`](https://api.drupal.org/api/drupal/core%21modules%21contextual%21contextual.module/function/contextual_page_attachments/9.3.x) ca exemplu despre ceea ce face core Drupal. IMO, dacă modalitatea corectă de a adăuga cod JavaScript ar fi adăugarea unui bloc, core Drupal ar face asta.
apaderno avatar
drapel us
A se vedea, de asemenea, conținutul [contextual.libraries.yml](https://api.drupal.org/api/drupal/core%21modules%21contextual%21contextual.libraries.yml/9.3.x), din care este clar că Biblioteca *drupal.contextual-links* conține cod JavaScript.
sonfd avatar
drapel in
Cred că aveți nevoie doar de o definiție mai completă a ceea ce înseamnă „după ștergerea memoriei cache”. Este acesta un adevăr absolut pentru univers în momentul în care memoria cache a fost golită? Trebuie să fie un utilizator pe site înainte ca cache-ul să fie șters pentru ca acesta să fie semnificativ? Este o perioadă de timp care durează X secunde după golirea memoriei cache?
sonfd avatar
drapel in
Modul în care încercați să utilizați starea nu va funcționa. Js-ul dvs. va fi atașat doar pentru o singură cerere de pagină de la o singură persoană din univers după o ștergere a memoriei cache.
apaderno avatar
drapel us
@sonfd Codul poate fi modificat pentru a adăuga biblioteca la primele X solicitări de pagini făcute după ce cache-ul este golit. Totuși, nu înțeleg de ce a fost adăugat după ștergerea cache-ului. Probabil, a vedea ce cod JavaScript este atașat și de ce ar ajuta la oferirea unui răspuns mai bun.
Puncte:2
drapel cn

Nu aș folosi Drupal::state() sau hook_page_attachments(), acestea sunt prea statice. Mai bine folosiți o valoare de sesiune și un bloc, vedeți comentariul meu în întrebarea anterioară.

Setați valoarea sesiunii în hook când memoria cache este șters și numai dacă nu rulează din linia de comandă:

funcția flush_cache_flush() {
  if (PHP_SAPI !== 'cli') {
    \Drupal::request()->getSession()->set('run_flush_js', TRUE);
  }
}

În bloc, verificați valoarea sesiunii și eliminați-o pentru a nu persista după redirecționare.

src/Plugin/Block/FlushBlock.php

<?php

spațiu de nume Drupal\flush\Plugin\Block;

utilizați Drupal\Core\Block\BlockBase;

/**
 * Oferă un bloc de spălare.
 *
 * @Bloc(
 * id = "flush_flush",
 * admin_label = @Translation("Flush"),
 * categorie = @Translation(„Personalizat”)
 * )
 */
clasa FlushBlock extinde BlockBase {

  /**
   * {@inheritdoc}
   */
  public function build() {
    $session = \Drupal::request()->getSession();  
    $build = [];
    dacă ($session->get('run_flush_js')) {
      $session->remove('run_flush_js');
      $build['conținut'] = [
        '#markup' => '<div class="run-flush-js"></div>',
        '#attached' => ['library' => ['flush/flush']],
      ];
    }
    $build['#cache']['max-age'] = 0;
    returnează $build;
  }
}

js/flush.js

(funcție ($, Drupal, o dată) {
  „utilizați strict”;

  Drupal.behaviors.flush = {
    /**
     * Comportamentul de ataşare Drupal.
     */
    atașați: funcție (context, setări) {
      if (o dată('flush', '.run-flush-js', context).length) {
        alert("bush!");
      }
    }
  };
})(jQuery, Drupal, o dată);

flush.libraries.yml

culoare:
  js:
    js/flush.js: {}
  dependențe:
    - miez/drupal
    - core/jquery
    - miez/o dată

Editare: Actualizați codul js, vedeți Cum pot face ca acest cod JavaScript să fie executat când modulul BigPipe este activat?

apaderno avatar
drapel us
`hook_page_attachments()` este folosit pentru a adăuga condiționat atașamente la o pagină înainte ca aceasta să fie redată, iar API-ul de stare este folosit pentru a stoca valorile stării site-ului. OP nu face nimic greșit în utilizarea lor. Alternativa sugerată are dezavantajele sale: o valoare de sesiune este pentru fiecare utilizator și trebuie adăugat un bloc într-o regiune a temei (ceea ce înseamnă, de asemenea, că schimbarea temei ar putea face ca biblioteca să nu fie adăugată).
apaderno avatar
drapel us
Apoi, utilizarea unui bloc și a unei valori de sesiune nu va rezolva problema pe care OP-ul o observă. Ar putea fi OP-ul a editat fișierul .libraries.yml după instalarea modulului sau OP-ul editează fișierul .libraries.yml greșit (ceea ce se poate întâmpla și pentru că există două copii ale aceluiași modul); în ambele cazuri, schimbarea modului în care biblioteca este adăugată la pagină nu rezolvă problema reală.
4uk4 avatar
drapel cn
Cred că ai nevoie de o sesiune, fără să rulezi javascript pe un client aleatoriu, oricine solicită prima pagină după ștergerea cache-ului. Există și alte moduri decât un bloc, dar este probabil cea mai rapidă, deoarece puteți utiliza sistemul cum redă paginile Drupal. Acest lucru funcționează chiar și cu BipPipe. L-am testat cu și fără și puteți vedea cum afectează acest lucru încărcarea paginii.
apaderno avatar
drapel us
OP nu a spus că vrea să ruleze codul JavaScript pentru același utilizator care a determinat ștergerea cache-ului; dacă acesta ar fi cazul, totuși, utilizarea unei valori de sesiune nu este necesară, deoarece utilizatorul care a determinat ștergerea cache-ului ar vizita cel puțin două pagini diferite sau aceeași pagină de două ori. Chiar și presupunând că OP ar dori să fie sigur că adaugă codul JavaScript la pagina solicitată de utilizatorul care a determinat ștergerea cache-ului (ceea ce nu are sens, deoarece memoria cache este șters pentru fiecare utilizator), ar fi suficient să stocați ID-ul utilizatorului folosind API-ul de stat.
apaderno avatar
drapel us
Acest lucru are sens deoarece utilizatorul care a fost autentificat atunci când memoria cache a fost șters este o valoare de stare pentru site, nu o valoare de sesiune.
Puncte:1
drapel in

Cred că ar trebui să abordezi asta altfel. Iată ce aș face:

Mai întâi, implementați hook_cache_flush() și utilizați-l pentru a stoca ultimul timp de spălare a cache-ului în starea Drupal.

funcția flush_cache_flush() {
  \Drupal::state()->set('flush_cache_cleared', time());
}

Apoi, utilizați hook_page_attachments() pentru a atașa întotdeauna javascript-ul pe fiecare pagină, dar transmiteți marca temporală golită din cache la javascript.

funcția flush_page_attachments(array &$attachments) {
  $attachments['#attached']['library'][] = 'spașare/încărcare';
  $attachments['#attached']['drupalSettings']['flush_cache_cleared'] = \Drupal::state()->get('flush_cache_cleared');
}

În sfârșit, în javascript, verificați dacă noua oră de golire a memoriei cache este mai recentă decât cea anterioară (va trebui să o stocați pe partea clientului prin stocare locală sau ceva).

Dacă orele sunt diferite, știți că memoria cache a fost șters.

(funcție ($, Drupal, drupalSettings) {
  „utilizați strict”;

  Drupal.behaviors.flush = {
    atașați: funcție (context, setări) {

      let cacheFlushedTime = drupalSettings['flush_cache_cleared'];
      // Faceți chestii cu cache_flushed_time aici, cum ar fi
      // comparați-l cu un timp de golire a cache-ului cunoscut anterior...

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

Postează un răspuns

Majoritatea oamenilor nu înțeleg că a pune multe întrebări deblochează învățarea și îmbunătățește legătura interpersonală. În studiile lui Alison, de exemplu, deși oamenii își puteau aminti cu exactitate câte întrebări au fost puse în conversațiile lor, ei nu au intuit legătura dintre întrebări și apreciere. În patru studii, în care participanții au fost implicați în conversații ei înșiși sau au citit transcrieri ale conversațiilor altora, oamenii au avut tendința să nu realizeze că întrebarea ar influența – sau ar fi influențat – nivelul de prietenie dintre conversatori.