Score:2

ฉันจะกำหนดไลบรารีอย่างถูกต้องได้อย่างไรเพื่อให้ JS ดำเนินการหลังจากตรงตามเงื่อนไขที่กำหนด

ธง cn

ฉันกำลังสร้างโมดูลที่กำหนดเองเพื่อเรียกใช้ JS หลังจากล้างแคชแล้ว นี่คือโครงสร้างของโมดูล:

โมดูล -> flush.info.yml

ชื่อ: ฟลัช
ประเภท: โมดูล
คำอธิบาย: โมดูลที่สำคัญมาก
แพคเกจ: กำหนดเอง
รุ่น: 1.0
core_version_requirement: ^8 || ^9

โมดูล -> flush.libraries.yml

ล้าง:
  รุ่น: 1.x
  จส:
    js/flush.js: {}
  การพึ่งพา:
    - แกน / jquery
    - การตั้งค่าหลัก / drupal

โมดูล -> flush.module

<?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'][] = 'ล้าง/ล้าง';
     \Drupal::state()->set('flush_cache_cleared', FALSE);
    }
  }

โมดูล -> JS -> flush.js

(ฟังก์ชัน ($, Drupal, drupalSettings) {
    'ใช้อย่างเข้มงวด';

    Drupal.behaviors.flush = {
      /**
       * พฤติกรรมการแนบ Drupal
       */
      แนบ: ฟังก์ชัน (บริบท การตั้งค่า) {
        this.settings = this.getSettings(การตั้งค่า);
        alert("ล้าง!");
        console.log ("สวัสดีชาวโลก");
      },
    };
  })(jQuery, Drupal, drupalSettings);

ทั้งสองฟังก์ชันใน flush.module ทำงานได้อย่างถูกต้อง อย่างไรก็ตาม JS ที่เป็น #attached ซึ่งควรจะใช้การ alert() ไม่เคยทำงาน ฉันเชื่อว่าปัญหาเกี่ยวข้องกับบรรทัดนี้โดยเฉพาะ: $attachments['#attached']['library'][] = 'ล้าง/ล้าง';

มีบางอย่างที่ชัดเจนว่าฉันทำผิดหรือไม่? ฉันใช้ page_attachments เป็นวิธีการแนบ JS เนื่องจากไม่จำเป็นต้องเชื่อมโยงกับส่วนใดส่วนหนึ่งของหน้าหรืออาร์เรย์การแสดงผล ฯลฯ โปรดแจ้งให้เราทราบหากคุณมีความคิดที่เป็นไปได้เกี่ยวกับปัญหาที่อาจเกิดขึ้น เป็นขอบคุณ!

sonfd avatar
in flag
จะเกิดอะไรขึ้นถ้าคุณเรียกใช้โดยไม่มีคำสั่ง if ใน hook_page_attachments
Joseph avatar
cn flag
@sonfd JS ยังใช้งานไม่ได้ ฉันรู้ว่าคำสั่ง if ทริกเกอร์ตามที่ตั้งใจไว้เพราะถ้าฉันสะท้อนคำสั่ง JS alert() ภายในคำสั่ง คำสั่งนั้นทริกเกอร์ เมื่อฉันพยายามแนบ JS ผ่านไลบรารีเท่านั้นที่ไม่มีอะไรเกิดขึ้น
Jaypan avatar
de flag
คุณล้างแคชหลังจากเพิ่มรหัสนั้นหรือไม่
Joseph avatar
cn flag
@Jaypan ใช่การล้างแคชใช้งานได้และถ้าฉันเพิ่ม JS ลงในฟังก์ชัน flush_page_attachments() มันจะทำงานตามที่ตั้งใจไว้ (เช่น การแจ้งเตือนเมื่อแคชถูกล้าง) อย่างไรก็ตามการใช้ไลบรารีซึ่งเป็นวิธีที่ถูกต้อง ไม่ทำงาน .
fr flag
มันถูกต้องอย่างสมบูรณ์ที่จะแนบไลบรารี่ภายใน hook_page_attachments() เหมือนที่คุณพยายามทำ - ฉันมีรหัสการทำงานที่ทำอย่างนั้น ฉันไม่เห็นอะไรผิดปกติกับ hook_page_attachments() ของคุณ แต่ถ้าคุณเพิ่มหรือเปลี่ยน flush.libraries.yml หลังจากที่คุณเปิดใช้งานโมดูล flush แล้ว ไฟล์ไลบรารีใหม่อาจไม่ถูกดึงขึ้นมา ลองถอนการติดตั้งและติดตั้งโมดูลของคุณอีกครั้ง
Jaypan avatar
de flag
นั่นคือประเด็นของฉัน
Joseph avatar
cn flag
การล้างแคชไม่ได้ทำให้ไลบรารีของฉันทำงาน และไม่ได้ถอนการติดตั้งและติดตั้งโมดูลแบบกำหนดเองใหม่เมื่อฉันเพิ่ม JS ใน hook_page_attachments() (เช่น การแจ้งเตือน) ดูเหมือนว่าจะเด้งขึ้นมาหลังจากที่แคชถูกล้าง แต่ก่อนที่จะโหลดหน้าซ้ำ นี่อาจเป็นสาเหตุที่ JS ที่แนบมาผ่านไลบรารีไม่ปรากฏ ฉันรู้สึกว่าควรเรียกการแจ้งเตือนเหมือนเดิมเมื่อเพิ่มลงใน hook_page_attachments() โดยตรง ไม่แน่ใจว่า
apaderno avatar
us flag
คุณแน่ใจหรือว่าคุณกำลังแก้ไขไฟล์ที่ถูกต้อง? คุณตรวจสอบหรือไม่ว่าโมดูลไม่ได้ถูกคัดลอกในไดเร็กทอรีสองไดเร็กทอรีที่ต่างกัน
apaderno avatar
us flag
การแนบโค้ด JavaScript เป็นไลบรารีคือสิ่งที่ Drupal core ทำ มันยังใช้ตะขอเดียวกันกับที่คุณใช้ หากมีสิ่งผิดปกติ นั่นไม่ใช่ตะขอที่ใช้แล้ว ดู [`contextual_page_attachments()`](https://api.drupal.org/api/drupal/core%21modules%21contextual%21contextual.module/function/contextual_page_attachments/9.3.x) เป็นตัวอย่างการทำงานของ Drupal core IMO ถ้าวิธีที่ถูกต้องในการเพิ่มโค้ด JavaScript คือการเพิ่มบล็อก Drupal core ก็จะทำเช่นนั้น
apaderno avatar
us flag
ดูเนื้อหาของ [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 flag
ฉันคิดว่าคุณต้องการคำจำกัดความที่สมบูรณ์กว่านี้ว่า “หลังจากล้างแคชแล้ว” หมายถึงอะไร นั่นคือความจริงแท้สำหรับจักรวาลในขณะที่แคชถูกล้างหรือไม่? ผู้ใช้จำเป็นต้องอยู่ในไซต์ก่อนที่จะล้างแคชเพื่อให้มีความสำคัญหรือไม่ เป็นระยะเวลา X วินาทีหลังจากล้างแคชหรือไม่
sonfd avatar
in flag
วิธีที่คุณพยายามใช้สถานะจะไม่ทำงาน js ของคุณจะถูกแนบสำหรับคำขอหน้าเดียวอย่างแท้จริงจากบุคคลเดียวในจักรวาลหลังจากล้างแคชแล้ว
apaderno avatar
us flag
@sonfd รหัสสามารถเปลี่ยนแปลงได้เพื่อเพิ่มไลบรารีไปยังคำขอ X หน้าแรกที่ทำหลังจากล้างแคชแล้ว ฉันไม่เข้าใจว่าทำไมมันถึงถูกเพิ่มหลังจากล้างแคชแล้ว อาจเป็นไปได้ว่าการดูว่าโค้ด JavaScript ใดแนบอยู่และทำไมจะช่วยให้คำตอบดีขึ้น
Score:2
ธง cn

ฉันจะไม่ใช้ Drupal::state() หรือ hook_page_attachments() สิ่งเหล่านี้คงที่เกินไป ใช้ค่าเซสชันและบล็อกได้ดีขึ้น ดู ความคิดเห็นของฉัน ในคำถามก่อนหน้า

ตั้งค่าเซสชันใน hook เมื่อแคชถูกล้างและเฉพาะเมื่อไม่ได้เรียกใช้จากบรรทัดคำสั่ง:

ฟังก์ชัน flush_cache_flush () {
  ถ้า (PHP_SAPI !== 'cli') {
    \Drupal::request()->getSession()->set('run_flush_js', TRUE);
  }
}

ในบล็อกให้ตรวจสอบค่าเซสชันและลบออกเพื่อไม่ให้คงอยู่หลังจากเปลี่ยนเส้นทาง

src/Plugin/Block/FlushBlock.php

<?php

เนมสเปซ Drupal\flush\Plugin\Block;

ใช้ Drupal\Core\Block\BlockBase;

/**
 * ให้บล็อกฟลัช
 *
 * @ปิดกั้น(
 * id = "flush_flush",
 * admin_label = @Translation("ฟลัช"),
 * หมวดหมู่ = @Translation("กำหนดเอง")
 * )
 */
class FlushBlock ขยาย BlockBase {

  /**
   * {@inheritdoc}
   */
  สร้างฟังก์ชั่นสาธารณะ () {
    $session = \Drupal::request()->getSession();  
    $สร้าง = [];
    ถ้า ($ เซสชัน -> รับ ('run_flush_js')) {
      $session->remove('run_flush_js');
      $สร้าง['เนื้อหา'] = [
        '#markup' => '<div class="run-flush-js"></div>',
        '#attached' => ['library' => ['ล้าง/ล้าง']],
      ];
    }
    $build['#cache']['max-age'] = 0;
    ส่งคืน $build;
  }
}

js/flush.js

(ฟังก์ชัน ($, Drupal, ครั้งเดียว) {
  'ใช้อย่างเข้มงวด';

  Drupal.behaviors.flush = {
    /**
     * พฤติกรรมการแนบ Drupal
     */
    แนบ: ฟังก์ชัน (บริบท การตั้งค่า) {
      ถ้า (ครั้งเดียว ('ล้าง', '.run-flush-js', บริบท). ความยาว) {
        alert("ล้าง!");
      }
    }
  };
})(jQuery, Drupal, ครั้งเดียว);

flush.libraries.yml

ล้าง:
  จส:
    js/flush.js: {}
  การพึ่งพา:
    - หลัก / drupal
    - แกน / jquery
    - แกน/ครั้ง

แก้ไข: อัปเดตรหัส js ดู ฉันจะทำให้รหัส JavaScript นี้ทำงานได้อย่างไรเมื่อเปิดใช้งานโมดูล BigPipe

apaderno avatar
us flag
`hook_page_attachments()` ใช้เพื่อเพิ่มสิ่งที่แนบมาอย่างมีเงื่อนไขในหน้าก่อนที่จะแสดงผล และ state API ใช้เพื่อจัดเก็บค่าสถานะของไซต์ OP ไม่ได้ทำอะไรผิดในการใช้มัน ทางเลือกที่แนะนำมีข้อเสีย: ค่าเซสชันเป็นต่อผู้ใช้และจำเป็นต้องเพิ่มบล็อกลงในพื้นที่ธีม (ซึ่งหมายความว่าการเปลี่ยนธีมอาจทำให้ไลบรารีไม่ถูกเพิ่ม)
apaderno avatar
us flag
จากนั้น การใช้บล็อกและค่าเซสชันจะไม่สามารถแก้ไขปัญหาที่ OP สังเกตเห็นได้ อาจเป็นได้ว่า OP แก้ไขไฟล์ .libraries.yml หลังจากติดตั้งโมดูล หรือ OP กำลังแก้ไขไฟล์ .libraries.yml ผิด (ซึ่งอาจเกิดขึ้นได้เนื่องจากมีโมดูลเดียวกันสองชุด) ในทั้งสองกรณี การเปลี่ยนวิธีเพิ่มไลบรารีลงในเพจไม่สามารถแก้ไขปัญหาจริงได้
4uk4 avatar
cn flag
ฉันคิดว่าคุณต้องการเซสชัน โดยที่คุณไม่ต้องเรียกใช้จาวาสคริปต์บนไคลเอนต์แบบสุ่ม ใครก็ตามที่ร้องขอหน้าแรกหลังจากล้างแคชแล้ว มีวิธีอื่นนอกเหนือจากการบล็อก แต่อาจเป็นวิธีที่เร็วที่สุดเพราะคุณสามารถใช้ระบบที่ Drupal เรนเดอร์หน้าเว็บ ซึ่งวิธีนี้ใช้ได้กับ BipPipe ฉันได้ทดสอบทั้งแบบมีและไม่มี และคุณสามารถดูได้ว่าสิ่งนี้ส่งผลต่อการโหลดหน้าเว็บอย่างไร
apaderno avatar
us flag
OP ไม่ได้บอกว่าเขาต้องการเรียกใช้โค้ด JavaScript สำหรับผู้ใช้รายเดียวกันที่ทำให้แคชถูกล้าง หากเป็นกรณีนี้ ก็ไม่จำเป็นต้องใช้ค่าเซสชัน เนื่องจากผู้ใช้ที่ทำให้แคชถูกล้างจะเข้าชมหน้าเว็บที่แตกต่างกันอย่างน้อยสองหน้าหรือหน้าเดียวกันสองครั้ง แม้ว่า OP ต้องการให้แน่ใจว่าได้เพิ่มรหัส JavaScript ในหน้าที่ร้องขอโดยผู้ใช้ที่ทำให้เกิดการล้างแคช (ซึ่งไม่สมเหตุสมผล เนื่องจากแคชถูกล้างสำหรับผู้ใช้ทุกคน) ก็เพียงพอที่จะ เก็บ ID ผู้ใช้โดยใช้ state API
apaderno avatar
us flag
เป็นเรื่องที่สมเหตุสมผลเนื่องจากผู้ใช้ที่เข้าสู่ระบบเมื่อแคชถูกล้างเป็นค่าสถานะสำหรับไซต์ ไม่ใช่ค่าเซสชัน
Score:1
ธง in

ฉันคิดว่าคุณควรใช้วิธีนี้แตกต่างออกไป นี่คือสิ่งที่ฉันจะทำ:

ขั้นแรก ใช้ hook_cache_flush() และใช้เพื่อเก็บเวลาการล้างแคชล่าสุดไปยังสถานะ Drupal

ฟังก์ชัน flush_cache_flush () {
  \Drupal::state()->set('flush_cache_cleared', เวลา());
}

ต่อไป ใช้ hook_page_attachments() เพื่อแนบจาวาสคริปต์ของคุณในทุกหน้า แต่ส่งการประทับเวลาที่ล้างแคชไปยังจาวาสคริปต์ของคุณ

ฟังก์ชัน flush_page_attachments (อาร์เรย์ &$ ไฟล์แนบ) {
  $attachments['#attached']['library'][] = 'ล้าง/ล้าง';
  $attachments['#attached']['drupalSettings']['flush_cache_cleared'] = \Drupal::state()->get('flush_cache_cleared');
}

สุดท้าย ในจาวาสคริปต์ของคุณ ให้ตรวจสอบว่าเวลาล้างแคชใหม่เร็วกว่าเดิมหรือไม่ (คุณจะต้องจัดเก็บสิ่งนี้ในฝั่งไคลเอนต์ผ่านที่จัดเก็บในเครื่องหรืออย่างอื่น)

หากเวลาต่างกัน แสดงว่าแคชถูกล้างแล้ว

(ฟังก์ชัน ($, Drupal, drupalSettings) {
  'ใช้อย่างเข้มงวด';

  Drupal.behaviors.flush = {
    แนบ: ฟังก์ชัน (บริบท การตั้งค่า) {

      ให้ cacheFlushedTime = drupalSettings ['flush_cache_cleared'];
      // ทำสิ่งต่างๆ ด้วย cache_flushed_time ที่นี่ เช่น
      // เปรียบเทียบกับเวลาล้างแคชที่รู้จักก่อนหน้านี้...

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

โพสต์คำตอบ

คนส่วนใหญ่ไม่เข้าใจว่าการถามคำถามมากมายจะปลดล็อกการเรียนรู้และปรับปรุงความสัมพันธ์ระหว่างบุคคล ตัวอย่างเช่น ในการศึกษาของ Alison แม้ว่าผู้คนจะจำได้อย่างแม่นยำว่ามีคำถามกี่ข้อที่ถูกถามในการสนทนา แต่พวกเขาไม่เข้าใจความเชื่อมโยงระหว่างคำถามและความชอบ จากการศึกษาทั้ง 4 เรื่องที่ผู้เข้าร่วมมีส่วนร่วมในการสนทนาด้วยตนเองหรืออ่านบันทึกการสนทนาของผู้อื่น ผู้คนมักไม่ตระหนักว่าการถามคำถามจะมีอิทธิพลหรือมีอิทธิพลต่อระดับมิตรภาพระหว่างผู้สนทนา