6.8. Drupal で JavaScript/jQuery を扱う。behavior(ビヘイビア)とは何か?
まず始めに、独自の 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
インデントが 2 スペースになるように、字下げを守ることが重要です。これで js/custom.js ファイルを読み込みました。しかし、jQuery を動作させるにはこれだけでは不十分です。実は、Drupal コアは jQuery を必須としておらず、jQuery を読み込みません。次のように別途読み込む必要があります:
dependencies:
- core/jquery
また jQuery.once() も使用します。これはセレクターにイベントやメソッドを一度だけ割り当てるための、jQuery 用の独立したプラグインです。
dependencies:
- core/jquery
- core/jquery.once
というのも、これから書く JavaScript コードは、さまざまなイベントに対して Drupal によって何度も呼び出されるからです。そのため、この .once() メソッドが必要になります。
では、custom.js ファイルにコードを追加してみましょう:
(function ($) {
Drupal.behaviors.myModuleBehavior = {
attach: function (context, settings) {
$(context).find('.click-me').once('myCustomBehavior').click(function () {
alert('Hello, World!');
});
}
};
})(jQuery);
順番に見ていきましょう。
(function ($) {
})(jQuery);
jQuery のコードをこの構文で包むのは、Drupal では jQuery が .noConflict() モードで動作するためです。これはドル記号 $ を使えるようにし、かつ他の JavaScript フレームワークである Prototype や MooTools と競合しないようにするために必要です。これらのフレームワークに出会うことはおそらくないでしょう。jQuery が確固たる主導的地位を占めています。しかし、すべての jQuery コードをこの構文で包む必要があります。
(function ($) {
Drupal.behaviors.myModuleBehavior = {
attach: function (context, settings) {
}
};
})(jQuery);
そこで behavior にたどり着きます。Drupal で jQuery コードを書く場合、まず function ($) で包み、次に behavior で包む必要があります。behavior 名は一意でなければならず、この例では myModuleBehavior ですが、behavior ごとに名前を書く必要があります:
(function ($) {
Drupal.behaviors.myModuleBehavior = {
attach: function (context, settings) {
}
};
Drupal.behaviors.productPageBehavior = {
attach: function (context, settings) {
}
};
})(jQuery);
behavior の命名には camelCase を使います。behavior はページの読み込み時、そしてすべての AJAX リクエストのたびに呼び出されます。したがって、新しいコンテンツがサイトにアップロードされ既存サイトの構造に埋め込まれるとき、behavior のコードが毎回呼び出されます。これは次のものとは大きく異なります:
$(document).ready(function () {
// 何か凝ったことをする。
// Drupal ではこのようなコードを使わないこと。
});
こちらはページ読み込み時に一度だけ呼び出されます。
behavior を使い始めて、サイトで奇妙な挙動に気づいた場合、例えば jQuery によってブロックが何度も追加されるような場合:
(function ($) {
Drupal.behaviors.myModuleBehavior = {
attach: function (context, settings) {
// behavior はページ上で複数回呼び出されます。.once() 関数を使うのを忘れないでください。
$('.inner').append('<p>Test</p>');
}
};
})(jQuery);
AJAX リクエストのたびに、Test という段落がもう一つ追加されてしまいます。そのため、.once() 関数を追加する必要があります:
(function ($) {
Drupal.behaviors.myModuleBehavior = {
attach: function (context, settings) {
// behavior はページ上で複数回呼び出されます。.once() 関数を使うのを忘れないでください。
$('.inner').once('add-paragraph').append('<p>Test</p>');
}
};
})(jQuery);
behavior のもう一つの特徴は context 変数です。ページ読み込み時や ajax を通じて新しいコンテンツがサイトに追加されるたびに、すべての新しいコンテンツが 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 について質問があったり、追加のテーマについて提案があれば、コメントに書いてください。