Điểm:2

Làm cách nào để xác định đúng thư viện để JS sẽ thực thi sau khi đáp ứng một điều kiện nhất định?

lá cờ cn

Tôi đang tạo một mô-đun tùy chỉnh để thực thi một số JS SAU KHI xóa bộ đệm. Đây là cấu trúc của mô-đun:

Mô-đun -> flush.info.yml

tên: tuôn ra
loại: mô-đun
mô tả: Một mô-đun rất quan trọng.
gói: Tùy chỉnh
phiên bản: 1.0
core_version_requirement: ^8 || ^9

Mô-đun -> flush.libraries.yml

tuôn ra:
  phiên bản: 1.x
  js:
    js/flush.js: {}
  phụ thuộc:
    - lõi/jquery
    - lõi/drupalSettings

Mô-đun -> flush.module

<?php

sử dụng Drupal\Core\Form\FormStateInterface;

/**
 * Triển khai hook_cache_flush()
 */

  hàm flush_cache_flush() {
    \Drupal::state()->set('flush_cache_cleared', TRUE);
  }

  hàm flush_page_attachments(mảng &$attachments) {
    if (\Drupal::state()->get('flush_cache_cleared')) {
      $attachments['#attached']['library'][] = 'flush/flush';
     \Drupal::state()->set('flush_cache_cleared', FALSE);
    }
  }

Mô-đun -> JS -> flush.js

(hàm ($, Drupal, drupalSettings) {
    'Sử dụng nghiêm ngặt';

    Drupal.behaviors.flush = {
      /**
       * Hành vi đính kèm Drupal.
       */
      đính kèm: chức năng (bối cảnh, cài đặt) {
        this.settings = this.getSettings(cài đặt);
        cảnh báo ("tuôn ra!");
        console.log("Xin chào thế giới");
      },
    };
  })(jQuery, Drupal, drupalSettings);

Cả hai chức năng trong flush.module đều hoạt động bình thường, tuy nhiên, JS được #attached vốn được cho là sử dụng một cảnh báo () không bao giờ chạy. Tôi tin rằng vấn đề có liên quan cụ thể đến dòng này: $attachments['#attached']['library'][] = 'flush/flush';

Có điều gì đó rõ ràng tôi đang làm sai? Tôi đã sử dụng page_attachments làm phương thức để đính kèm JS vì nó không nhất thiết phải được liên kết với một phần cụ thể của trang hoặc mảng kết xuất, v.v. Vui lòng cho tôi biết nếu bạn có bất kỳ ý tưởng tiềm năng nào về vấn đề có thể xảy ra được, cảm ơn!

sonfd avatar
lá cờ in
Điều gì xảy ra nếu bạn chạy nó mà không có câu lệnh if trong hook_page_attachments?
Joseph avatar
lá cờ cn
@sonfd JS vẫn không hoạt động. Tôi biết câu lệnh if kích hoạt như dự định bởi vì nếu tôi lặp lại lệnh JS alert() bên trong nó, nó sẽ kích hoạt. Chỉ khi tôi cố gắng đính kèm JS qua thư viện thì không có gì xảy ra.
Jaypan avatar
lá cờ de
Bạn đã xóa bộ đệm sau khi thêm mã đó chưa?
Joseph avatar
lá cờ cn
@Jaypan Vâng, xóa bộ đệm hoạt động và nếu tôi thêm JS vào hàm flush_page_attachments() thì nó sẽ hoạt động như dự định (tức là cảnh báo khi bộ đệm bị xóa) tuy nhiên sử dụng thư viện là cách thực hiện chính xác thì không hoạt động .
lá cờ fr
Việc đính kèm thư viện bên trong hook_page_attachments() giống như bạn đang cố gắng thực hiện là hoàn toàn hợp lệ - Tôi có mã làm việc thực hiện điều đó. Tôi không thấy có gì sai với hook_page_attachments() của bạn. NHƯNG nếu bạn đã thêm hoặc thay đổi flush.libraries.yml sau khi bật mô-đun flush, thì tệp thư viện mới có thể không được chọn. Hãy thử gỡ cài đặt và cài đặt lại mô-đun của bạn.
Jaypan avatar
lá cờ de
Đó là quan điểm của tôi.
Joseph avatar
lá cờ cn
Xóa bộ đệm không làm cho thư viện của tôi hoạt động, cũng như việc gỡ cài đặt và cài đặt lại mô-đun tùy chỉnh.Khi tôi thêm JS vào hook_page_attachments() (giống như một cảnh báo), nó dường như bật lên sau khi xóa bộ nhớ cache nhưng trước khi tải lại trang. Đây có thể là lý do tại sao JS được đính kèm qua thư viện không xuất hiện? Tôi cảm thấy như nó vẫn sẽ kích hoạt một cảnh báo giống như khi nó được thêm trực tiếp vào hook_page_attachments(). Không chắc chắn mặc dù.
apaderno avatar
lá cờ us
Bạn có chắc là bạn đang chỉnh sửa đúng tệp không? Bạn đã kiểm tra mô-đun không được sao chép trong hai thư mục khác nhau chưa?
apaderno avatar
lá cờ us
Đính kèm mã JavaScript dưới dạng thư viện là điều cốt lõi của Drupal thực hiện. Nó thậm chí còn sử dụng chính cái móc mà bạn đang sử dụng. Nếu có bất cứ điều gì sai, đó không phải là móc đã qua sử dụng. Xem [`contextual_page_attachments()`](https://api.drupal.org/api/drupal/core%21modules%21contextual%21contextual.module/function/contextual_page_attachments/9.3.x) làm ví dụ về những gì lõi Drupal thực hiện. IMO, nếu cách chính xác để thêm mã JavaScript là thêm một khối, lõi Drupal sẽ làm điều đó.
apaderno avatar
lá cờ us
Xem thêm nội dung của [contextual.libraries.yml](https://api.drupal.org/api/drupal/core%21modules%21contextual%21contextual.libraries.yml/9.3.x), từ đó thấy rõ rằng Thư viện *drupal.contextual-links* chứa mã JavaScript.
sonfd avatar
lá cờ in
Tôi nghĩ bạn chỉ cần một định nghĩa đầy đủ hơn về ý nghĩa của sau khi xóa bộ nhớ cache. Đó có phải là một sự thật tuyệt đối cho vũ trụ tại thời điểm bộ nhớ cache bị xóa? Người dùng có cần phải ở trên trang web trước khi xóa bộ đệm để nó trở nên quan trọng không? Đây có phải là khoảng thời gian kéo dài X giây sau khi xóa bộ đệm không?
sonfd avatar
lá cờ in
Cách bạn đang cố sử dụng trạng thái sẽ không hoạt động. js của bạn sẽ chỉ được đính kèm theo nghĩa đen cho một yêu cầu trang đơn từ một người duy nhất trong vũ trụ sau khi xóa bộ đệm.
apaderno avatar
lá cờ us
@sonfd Có thể thay đổi mã để thêm thư viện vào các yêu cầu trang X đầu tiên được thực hiện sau khi xóa bộ đệm. Tuy nhiên, tôi không hiểu tại sao nó lại được thêm vào sau khi xóa bộ đệm. Có lẽ, việc xem mã JavaScript nào được đính kèm và tại sao sẽ giúp đưa ra câu trả lời tốt hơn.
Điểm:2
lá cờ cn

Tôi sẽ không sử dụng Drupal::state() hoặc hook_page_attachments(), chúng quá tĩnh. Sử dụng tốt hơn một giá trị phiên và một khối, xem nhận xét của tôi trong câu hỏi trước.

Đặt giá trị phiên trong hook khi bộ đệm bị xóa và chỉ khi không chạy từ dòng lệnh:

hàm flush_cache_flush() {
  nếu (PHP_SAPI !== 'cli') {
    \Drupal::request()->getSession()->set('run_flush_js', TRUE);
  }
}

Trong khối kiểm tra giá trị phiên và loại bỏ nó để nó không tồn tại sau khi chuyển hướng.

src/Plugin/Block/FlushBlock.php

<?php

không gian tên Drupal\flush\Plugin\Block;

sử dụng Drupal\Core\Block\BlockBase;

/**
 * Cung cấp một khối tuôn ra.
 *
 * @Chặn(
 * id = "flush_flush",
 * admin_label = @Translation("Flush"),
 * danh mục = @Translation("Tùy chỉnh")
 * )
 */
lớp FlushBlock mở rộng BlockBase {

  /**
   * {@inheritdoc}
   */
  xây dựng chức năng công cộng () {
    $session = \Drupal::request()->getSession();  
    $xây dựng = [];
    if ($session->get('run_flush_js')) {
      $session->remove('run_flush_js');
      $build['nội dung'] = [
        '#markup' => '<div class="run-flush-js"></div>',
        '#attached' => ['library' => ['flush/flush']],
      ];
    }
    $build['#cache']['max-age'] = 0;
    trả lại bản dựng $;
  }
}

js/flush.js

(hàm ($, Drupal, một lần) {
  'Sử dụng nghiêm ngặt';

  Drupal.behaviors.flush = {
    /**
     * Hành vi đính kèm Drupal.
     */
    đính kèm: chức năng (bối cảnh, cài đặt) {
      if (once('flush', '.run-flush-js', context).length) {
        cảnh báo ("tuôn ra!");
      }
    }
  };
})(jQuery, Drupal, một lần);

flush.libraries.yml

tuôn ra:
  js:
    js/flush.js: {}
  phụ thuộc:
    - lõi/drupal
    - lõi/jquery
    - lõi/một lần

Chỉnh sửa: Cập nhật mã js, xem Làm cách nào tôi có thể thực thi mã JavaScript này khi mô-đun BigPipe được bật?

apaderno avatar
lá cờ us
`hook_page_attachments()` được sử dụng để thêm các tệp đính kèm vào một trang theo điều kiện trước khi nó được hiển thị và API trạng thái được sử dụng để lưu trữ các giá trị trạng thái trang web. OP không làm gì sai khi sử dụng chúng. Phương án thay thế được đề xuất có nhược điểm: Giá trị phiên dành cho mỗi người dùng và một khối cần được thêm vào vùng chủ đề (điều này cũng có nghĩa là việc thay đổi chủ đề có thể khiến thư viện không được thêm vào).
apaderno avatar
lá cờ us
Sau đó, sử dụng khối và giá trị phiên sẽ không giải quyết được sự cố mà OP nhận thấy. Có thể OP đã chỉnh sửa tệp .libraries.yml sau khi cài đặt mô-đun hoặc OP đang chỉnh sửa tệp .libraries.yml sai (điều này cũng có thể xảy ra do có hai bản sao của cùng một mô-đun); trong cả hai trường hợp, việc thay đổi cách thư viện được thêm vào trang không khắc phục được vấn đề thực sự.
4uk4 avatar
lá cờ cn
Tôi nghĩ bạn cần một phiên mà không cần bạn chạy javascript trên một ứng dụng khách ngẫu nhiên, bất kỳ ai đang yêu cầu trang đầu tiên sau khi xóa bộ nhớ cache. Có nhiều cách khác ngoài chặn, nhưng đó có thể là cách nhanh nhất vì bạn có thể sử dụng hệ thống cách Drupal hiển thị các trang, Cách này hoạt động ngay cả với BipPipe. Tôi đã thử nghiệm có và không có tính năng này và bạn có thể thấy điều này ảnh hưởng đến việc tải trang như thế nào.
apaderno avatar
lá cờ us
OP không nói rằng anh ấy muốn chạy mã JavaScript cho cùng một người dùng đã khiến bộ đệm bị xóa; Tuy nhiên, trong trường hợp đó, việc sử dụng giá trị phiên là không cần thiết, vì người dùng đã xóa bộ nhớ đệm sẽ truy cập ít nhất hai trang khác nhau hoặc cùng một trang hai lần. Ngay cả khi giả sử OP muốn chắc chắn thêm mã JavaScript vào trang được yêu cầu bởi người dùng đã khiến bộ đệm bị xóa (điều này không hợp lý vì bộ đệm được xóa cho mọi người dùng), thì cũng đủ để lưu trữ ID người dùng bằng API trạng thái.
apaderno avatar
lá cờ us
Điều đó có ý nghĩa bởi vì người dùng đã đăng nhập khi bộ nhớ cache bị xóa là một giá trị trạng thái cho trang web, không phải giá trị phiên.
Điểm:1
lá cờ in

Tôi nghĩ bạn nên tiếp cận vấn đề này theo cách khác. Đây là những gì tôi sẽ làm:

Đầu tiên, triển khai hook_cache_flush() và sử dụng nó để lưu trữ thời gian xóa bộ nhớ cache cuối cùng sang trạng thái Drupal.

hàm flush_cache_flush() {
  \Drupal::state()->set('flush_cache_cleared', time());
}

Tiếp theo, sử dụng hook_page_attachments() để luôn đính kèm javascript của bạn trên mọi trang, nhưng chuyển dấu thời gian đã xóa bộ nhớ cache cho javascript của bạn.

hàm flush_page_attachments(mảng &$attachments) {
  $attachments['#attached']['library'][] = 'flush/flush';
  $attachments['#attached']['drupalSettings']['flush_cache_cleared'] = \Drupal::state()->get('flush_cache_cleared');
}

Cuối cùng, trong javascript của bạn, hãy kiểm tra xem thời gian xóa bộ đệm mới có gần đây hơn thời gian trước không (bạn sẽ cần lưu trữ thời gian này ở phía máy khách thông qua bộ nhớ cục bộ hoặc thứ gì đó).

Nếu thời gian khác nhau, bạn biết bộ đệm đã bị xóa.

(hàm ($, Drupal, drupalSettings) {
  'Sử dụng nghiêm ngặt';

  Drupal.behaviors.flush = {
    đính kèm: chức năng (bối cảnh, cài đặt) {

      để cacheFlushedTime = drupalSettings['flush_cache_cleared'];
      // Làm mọi thứ với cache_flushed_time ở đây, như
      // so sánh nó với thời gian xóa bộ nhớ cache đã biết trước đó...

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

Đăng câu trả lời

Hầu hết mọi người không hiểu rằng việc đặt nhiều câu hỏi sẽ mở ra cơ hội học hỏi và cải thiện mối quan hệ giữa các cá nhân. Ví dụ, trong các nghiên cứu của Alison, mặc dù mọi người có thể nhớ chính xác có bao nhiêu câu hỏi đã được đặt ra trong các cuộc trò chuyện của họ, nhưng họ không trực giác nhận ra mối liên hệ giữa câu hỏi và sự yêu thích. Qua bốn nghiên cứu, trong đó những người tham gia tự tham gia vào các cuộc trò chuyện hoặc đọc bản ghi lại các cuộc trò chuyện của người khác, mọi người có xu hướng không nhận ra rằng việc đặt câu hỏi sẽ ảnh hưởng—hoặc đã ảnh hưởng—mức độ thân thiện giữa những người đối thoại.