9.3 向组件添加 Javascript/CSS/库
Drupal 7 里,推荐使用渲染数组里的 #attached 向组件添加 JavaScript 或 CSS 。许多开发者也使用 drupal_add_js
,
drupal_add_css
和 drupal_add_library
。Drupal 8 只支持 #attached
。所以现在推荐把所有的 JavaScript 和 CSS 定义为一个库,之后附加到渲染数组。
创建一个库
模块的 libraries.yml 文件把你渲染页面所需要的 CSS 和 JavaScript 定义为库。这个文件指定了库中每个组件的位置。
辅助内容区是 theme_example.libraries.yml 例子。在这个例子中,我们只定义了一个库 sample-library。它包含 JavaScript 和 CSS,也依赖几个核心库。Drupal 7 里,我们假定 jQuery,jQuery.once
和 settings 是有效的。Drupal 8 ,你必须把这些定义为依赖,因为默认它们不会被加载。
这两个 CSS 例子可以在库中使用:
myElement {
border: 3px solid purple;
border-radius: 3px;
padding: 1em;
margin: 1em;
background-color: #EEE;
}
.myElement .randomNumber {
color: purple;
font-weight: bold;
font-size: 1.2em;
}
sample_library:
css:
# For some reason, you need to put css under 'theme'.
theme:
css/example.css: {}
js:
# For some reason, you need to put the js directly under 'js'.
js/example.js: {}
dependencies:
# jQuery is not included by default, so we add it as a dependency
- core/jquery
# We are also going to use jQuery.once so that code doesn't trigger multiple times.
- core/jquery.once
# drupal and drupalSettings are not included by default either.
- core/drupal
向组件附加库
我们已经有了库,现在可以在渲染数组内引用了。
$output = [
'#markup' => '<div>hello world</div>',
'#attached => [
'library' => [
'theme_example/sample_library',
],
],
];
我们也可以定义一个传递给 JavaScript 的设置。
$output = [
'#markup' => '<div>hello world</div>',
'#attached => [
// This setting will be sent to drupalSettings.sampleLibrary.mySetting.
'drupalSettings' => [
'sampleLibrary' => [
'mySetting' => 'hello world',
],
],
],
];
更新插件 #pre_render 函数:
/**
* Prepare the render array for the template.
*/
public static function preRenderMyElement($element) {
// Create a link render array using our #label.
$element['link'] = [
'#type' => 'link',
'#title' => $element['#label'],
'#url' => Url::fromUri('http://www.drupal.org'),
];
// Create a description render array using #description.
$element['description'] = [
'#markup' => $element['#description']
];
$element['pre_render_addition'] = [
'#markup' => 'Additional text.'
];
// Create a variable.
$element['#random_number'] = rand(0,100);
// Add the library
$element['#attached'] = [
'library' => [
'theme_example/sample_library',
],
'drupalSettings' => [
'sampleLibrary' => [
'mySetting' => 'hello world',
],
],
];
return $element;
}
Drupal 8 中的 JavaScript 模式
JavaScript 的最佳实践与 Drupal 7 相同。我们把 jQuery 对象包裹在一个闭包内,把函数附加在 Drupal.behaviors 上。主要的变化是:设置变量现在是 drupalSettings 。
(function ($) {
Drupal.behaviors.themeExample = {
attach: function (context, settings) {
// jQuery once ensures that code does not run after an AJAX or other function that calls Drupal.attachBehaviors().
$('body').once('themeExample').each(function () {
// We have console.log() here to make it easy to see that this code is functioning. You should never use console.log() on production code!
if (typeof console.log === 'function') {
console.log('My Setting: ' + settings.sampleLibrary.mySetting);
}
});
if (typeof console.log === 'function') {
console.log('This will run every time Drupal.attachBehaviors is run.');
}
$('body').once('themeExampleModifyDOM').each(function () {
// Add an element to the body.
$('body').append('<div>Hello World</div>');
// Tell Drupal that we modified the DOM.
Drupal.attachBehaviors();
});
}
};
})(jQuery);
测试库是否工作
导航到路径 /examples/theme-example/simple,使用 Chrome 或 FireFox 查看控制台。你会看到 JavaScript 库产生的消息。
文件
这个练习中应该有这些文件:
- theme_example.info.yml
- theme_example.routing.yml
- theme_example.libraries.yml
- theme_example.module
- cs/example.css
- js/example.js
- src/Element/MyElement.php
- src/Controller/ThemeExampleController.php
- templates/my-element.html.twig