在 Drupal 8 模块中添加样式表 (CSS) 和 JavaScript (JS)
本指南适用于模块。关于主题的信息,请参阅 在 Drupal 8 主题中添加样式表 (CSS) 和 JavaScript (JS)。
在 Drupal 8 中,样式表 (CSS) 和 JavaScript (JS) 的加载通过同一个资源库系统完成,适用于模块(代码)和主题。资源库可以包含一个或多个 CSS 文件、一个或多个 JS 文件以及一个或多个 JS 配置。
Drupal 遵循一个高级原则:资源 (CSS 或 JS) 只有在你告诉 Drupal 需要加载时才会被加载。Drupal 不会在所有页面上加载所有资源 (CSS/JS),因为这会对前端性能产生负面影响。
与 Drupal 7 的区别
对开发者而言,Drupal 7 与 Drupal 8 有两个重要区别:
1. 只有特定页面所需的 JavaScript 才会被添加到该页面。特别是,对于大多数匿名用户可见的页面,Drupal 默认不加载 JavaScript。这意味着 jQuery 不再自动加载到所有页面。
因此,如果你的主题需要 jQuery 或其他 JavaScript(且这些脚本也定义在资源库中),你需要显式声明依赖关系。
2. Drupal.settings 对象被替换为 drupalSettings。
流程
加载资源 (CSS / JS) 的基本步骤:
1. 将 CSS 或 JS 保存到文件中。
2. 定义一个“资源库”,它可以包含 CSS 和 JS 文件。
3. 在 hook 中将该资源库“附加”到渲染数组。
但对于主题而言,还有另一种选择:主题可以在所有页面上加载任意数量的资源库。
定义资源库
要定义一个或多个资源库,请在模块根目录下(与 .info.yml 文件在同一目录)添加一个 *.libraries.yml 文件。如果你的模块名为 fluffiness,则文件名应为 fluffiness.libraries.yml。每个资源库是一个条目,描述 CSS 和 JS 文件,例如:
cuddly-slider:
version: 1.x
css:
layout:
css/cuddly-slider-layout.css: {}
theme:
css/cuddly-slider-theme.css: {}
js:
js/cuddly-slider.js: {}
注意 CSS 中有 'layout' 和 'theme' 键,而 JS 中没有。这些键表示 CSS 文件的样式类别。
你可以用 5 种不同的样式级别来设置 CSS 权重:
- base: CSS reset/normalize 以及 HTML 元素的基础样式。权重 = -200
- layout: 页面宏观布局,包括网格系统。权重 = -100
- component: 可复用的 UI 组件。权重 = 0
- state: 与组件状态变化相关的样式。权重 = 100
- theme: 与视觉外观相关的样式。权重 = 200
这遵循 SMACSS 标准。
在这个例子中,cuddly-slider.js 位于模块的 js 子目录下。你也可以引用外部 JS 或 CSS,详见 CDN/外部库。
由于 Drupal 8 默认不在所有页面加载 jQuery,我们必须声明 cuddly-slider 库依赖于 core/jquery:
cuddly-slider:
version: 1.x
css:
theme:
css/cuddly-slider.css: {}
js:
js/cuddly-slider.js: {}
dependencies:
- core/jquery
CSS 和 JS 的加载顺序与定义顺序一致。
默认情况下,Drupal 将 JS 加载到页面底部,以避免阻塞 DOM 加载。如果你需要在 <head> 部分加载,可以设置 header 参数:
cuddly-slider:
version: 1.x
header: true
js:
js/cuddly-slider.js: {}
这样 cuddly-slider.js 就会加载在页面顶部。
将资源库附加到页面
根据所需的资源,你可以以不同方式附加资源库。关键不是基于 URL 或路由来决定,而是基于页面上显示的“元素”。例如,如果页面包含 '#type' => 'table',则只加载与 table 相关的库。
下面是几种方式:
附加到所有某个 “#type”
function yourmodule_element_info_alter(array &$types) {
if (isset($types['table'])) {
$types['table']['#attached']['library'][] = 'your_module/library_name';
}
}
附加到渲染数组
$build['element']['#attached']['library'][] = 'your_module/library_name';
附加到 Block 插件
return [
'#theme' => 'your_module_theme_id',
'#attached' => [
'library' => ['your_module/library_name'],
],
];
附加到表单
function yourmodule_form_alter(&$form, FormStateInterface $form_state, $form_id) {
$form['#attached']['library'][] = 'yourmodule/yourlibrary';
}
附加到所有页面
function contextual_page_attachments(array &$page) {
if (\Drupal::currentUser()->hasPermission('access contextual links')) {
$page['#attached']['library'][] = 'contextual/drupal.contextual-links';
}
}
附加到 Twig 模板
{{ attach_library('your_module/library_name') }}
<div>Some markup {{ message }}</div>
附加 drupalSettings
$build['#attached']['library'][] = 'your_module/library_name'; $build['#attached']['drupalSettings']['fluffiness']['cuddlySlider'] = [ 'foo' => 'bar', 'baz' => 'qux', ];
禁用聚合
cuddly-slider:
version: 1.x
js:
js/cuddly-slider.js: { preprocess: false }