logo

额外区块类型 (EBT) - 全新的布局构建器体验❗

额外区块类型 (EBT) - 样式化、可定制的区块类型:幻灯片、标签页、卡片、手风琴等更多类型。内置背景、DOM Box、JavaScript 插件的设置。立即体验布局构建的未来。

演示 EBT 模块 下载 EBT 模块

❗额外段落类型 (EPT) - 全新的 Paragraphs 体验

额外段落类型 (EPT) - 类似的基于 Paragraph 的模块集合。

演示 EPT 模块 滚动

滚动

6.8. 在 Drupal 中使用 JavaScript / jQuery:什么是 Behaviors?

17/10/2025, by Ivan

首先,让我们回顾一下如何在主题中引入自定义 JavaScript 文件。在 .libraries.yml 文件中,我们需要添加 js 部分:

global-styling:
  version: 1.x
  css:
    theme:
      css/style.css: {}
      css/print.css: { media: print }
  js:
    js/custom.js: {}
  dependencies:
    - core/jquery
    - core/jquery.once

请注意缩进,必须为两个空格。这样,我们就包含了 js/custom.js 文件。但仅仅这样还不够,Drupal 核心默认并不会自动加载 jQuery。要启用 jQuery,必须显式地声明依赖:

dependencies:
  - core/jquery

此外,我们还使用 jQuery.once() 插件,它可以确保事件和方法只绑定到选择器一次,避免重复执行。

dependencies:
  - core/jquery
  - core/jquery.once

这是因为在 Drupal 中,我们编写的 JavaScript 代码可能会在不同事件中多次触发。因此,为了防止重复执行,我们需要使用 .once() 方法。

现在我们在 custom.js 文件中添加一些示例代码:

(function ($) {
  Drupal.behaviors.myModuleBehavior = {
    attach: function (context, settings) {
      $(context).find('.click-me').once('myCustomBehavior').click(function () {
        alert('Hello, World!');
      });
    }
  };
})(jQuery);

让我们逐步理解这段代码。

首先,Drupal 中的 jQuery 运行在 .noConflict() 模式下,因此不能直接使用 $,必须用这种写法:

(function ($) {

})(jQuery);

这样,我们就可以在内部安全地使用 $ 符号,而不会与其他 JavaScript 框架(例如 Prototype、MooTools)冲突。

接下来是 Drupal 的核心概念 —— Behaviors(行为)

(function ($) {
  Drupal.behaviors.myModuleBehavior = {
    attach: function (context, settings) {

    }
  };
})(jQuery);

当您在 Drupal 中编写 jQuery 代码时,必须同时使用 function ($) 封装和 behavior 行为定义。每个 behavior 名称必须唯一,例如这里的 myModuleBehavior。可以定义多个 behavior:

(function ($) {
  Drupal.behaviors.myModuleBehavior = {
    attach: function (context, settings) {

    }
  };

  Drupal.behaviors.productPageBehavior = {
    attach: function (context, settings) {

    }
  };
})(jQuery);

命名行为时应使用 camelCase(驼峰命名)。Behavior 会在页面加载时触发,也会在每次 AJAX 请求后再次执行。这意味着当新内容通过 AJAX 加载并插入页面结构时,Behavior 中的代码都会再次运行。这与以下旧式写法不同:

$(document).ready(function () {
  // 执行一些代码
  // 请不要在 Drupal 中使用这种写法
});

该写法只会在页面首次加载时执行一次,而不会在 AJAX 更新后再次触发。

如果您在使用 Behavior 时发现某些事件被多次执行,例如多次添加了一个区块,可以参考以下错误示例:

(function ($) {
  Drupal.behaviors.myModuleBehavior = {
    attach: function (context, settings) {
      // Behavior 会在页面上多次被调用,不要忘记使用 .once() 函数。
      $('.inner').append('<p>Test</p>');
    }
  };
})(jQuery);

此时,每次 AJAX 请求都会新增一个 <p>Test</p> 段落。解决方法是使用 .once()

(function ($) {
  Drupal.behaviors.myModuleBehavior = {
    attach: function (context, settings) {
      // Behavior 会在页面上多次被调用,不要忘记使用 .once() 函数。
      $('.inner').once('add-paragraph').append('<p>Test</p>');
    }
  };
})(jQuery);

context 变量也是 Behavior 的一个重要特性。每次当页面加载或通过 AJAX 添加新内容时,新插入的 DOM 元素都在 context 中。因此,我们不需要在每次 AJAX 请求后遍历整个 DOM,只需在 context 中查找目标元素即可:

(function ($) {
  Drupal.behaviors.myModuleBehavior = {
    attach: function (context, settings) {
      // Behavior 会在页面上多次被调用,不要忘记使用 .once() 函数。
      $(context).find('.inner').once('add-paragraph').append('<p>Test</p>');
    }
  };
})(jQuery);

这样写的代码就符合 Drupal 的标准风格。虽然仍可以使用传统的 $(document).ready(),但它仅在页面加载时执行一次,并且性能不如 Behavior。

如果您对 jQuery / JavaScript 或 Drupal 主题开发有任何疑问或建议,欢迎在评论中留言。