“中国要复兴、富强,必须在开源软件领域起到主导作用,为了国家安全和人类发展,责无旁贷,我们须为此而奋斗”——By:云客
在阅读本主题前,你需要先阅读本系列的渲染数组、渲染器、渲染占位符等主题
附属物attachments就是渲染数组的#attached部分,这里称为“附属物”而不叫做“附件”,以便和图片、文件等概念相区别,附属物有如下8个类型(以在#attached中的键名列出,如果添加了其他键名将引起错误):
library:资源库,保存css、js、库js设置等,详见本系列资源库详解
drupalSettings:在渲染数组中设置的JavaScript 设置数据
html_head:在 HTML <head>部分的标签
html_head_link: 在 HTML <head>部分的<link>标签,是html_head的特殊情况
feed:RSS 订阅,是html_head_link的特殊情况
http_header:HTTP 响应头和状态码等
placeholders:占位内容,严格说来这不算附属物,只是系统将其和附属物在同一个服务中处理
html_response_attachment_placeholders:保存四大类别附属物的占位符,见后
在系统中对附属物的处理是在派发kernel.response事件阶段:
订阅器服务:html_response.subscriber
类:\Drupal\Core\EventSubscriber\HtmlResponseSubscriber
执行方法:onRespond
优先级:0-0
该订阅器只针对html响应进行处理:
\Drupal\Core\Render\HtmlResponse
只是起到简单的订阅事件作用,全部附属物处理工作在附属物处理器中进行,见下。
附属物处理器:
负责在上述订阅器中对HTML响应进行附属物占位符替换处理
服务名:html_response.attachments_processor
类:Drupal\Core\Render\HtmlResponseAttachmentsProcessor
获取方法:\Drupal::service('html_response.attachments_processor');
该处理器只针对\Drupal\Core\Render\HtmlResponse响应,这也是系统HTML页面的主要响应,下文针对各类附属物单独讲解。
内容占位符placeholders:
placeholders严格说来不属于附属物,而是页面内容,往往是不合适缓存的需要动态产生的页面局部内容,需要内容占位的元素(元素即渲染数组)键名只能包含:'#lazy_builder', '#cache', '#create_placeholder','#weight', '#printed',其中'#lazy_builder'指定了一个回调用于产生真实内容的渲染数组,在html字符串中这样的内容先以占位符占位,占位符由渲染占位符产生器(服务id:render_placeholder_generator)产生,格式如下:
<drupal-render-placeholder callback="' . Html::escape($callback) . '" arguments="' . Html::escape($arguments) . '" token="' . Html::escape($token) . '"></drupal-render-placeholder>
渲染占位符产生器同时在渲染数组中$elements['#attached']['placeholders']中添加值,其是一个数组,键名为占位符,键值是一个数组,该数组只有两个键名:'#lazy_builder'用于指定返回新渲染数组的回调、'#cache'用于保存缓存源数据
对内容占位符的处理就是将响应(html字符串)中的内容占位符替换成真实内容,这一过程在渲染器中执行,真实内容由$elements['#attached']['placeholders']中占位符键名保存的回调产生(来自于渲染数组的'#lazy_builder'),回调会产生新的渲染数组,渲染器对其合并原缓存元数据,并渲染,用渲染结果去替换占位符。
该过程往往会产生新的缓存元数据和附属物,因此在附属物处理器中她需要首先处理,首先调用渲染器的$renderer->renderRoot($html)方法进行渲染,在返回后更新响应对象的缓存元数据和附属物,这样就可开始其他的附属物处理了。(读到这里是否感觉对drupal渲染管道有拨云见日的感觉呢,也明白什么叫根渲染了是吧)
附属物占位符html_response_attachment_placeholders:
保存4个类型(styles、scripts、scripts_bottom、head)附属物的占位符值,其中html_head、html_head_link、feed都是head类型,附属物替换就是替换她保存的占位符字符串,该内容是在以下预处理函数中添加的:
template_preprocess_html(&$variables)(位于core\includes\theme.inc)
(预处理函数有能力添加缓存元数据和附属物,逻辑位于主题管理器中,详见主题管理器和主题注册中预处理函数一节)。
此外在\Drupal\Core\Render\HtmlResponse中也有补充默认设置,该项值类似如下:
[html_response_attachment_placeholders] => Array
(
[styles]=>
<css-placeholder token="adoAt0nf3KI5PsdTh274WS4ttC5No7Ko6rIYzlf4jt-dg5Qm9EfISwA93gWuIlIZpGGhBkYodQ">
[scripts]=>
<js-placeholder token="adoAt0nf3KI5PsdTh274WS4ttC5No7Ko6rIYzlf4jt-dg5Qm9EfISwA93gWuIlIZpGGhBkYodQ">
[scripts_bottom]=>
<js-bottom-placeholder token="adoAt0nf3KI5PsdTh274WS4ttC5No7Ko6rIYzlf4jt-dg5Qm9EfISwA93gWuIlIZpGGhBkYodQ">
[head]=>
<head-placeholder token="adoAt0nf3KI5PsdTh274WS4ttC5No7Ko6rIYzlf4jt-dg5Qm9EfISwA93gWuIlIZpGGhBkYodQ">
)
头部通用标签html_head:
html头部标签(位于head区域的标签),来自渲染数组$renderArray['#attached']['html_head'],是由$head元素构成的一个数组,$head的格式如下:
$head = [$element , $name];
$element是单个头部标签的渲染数组,可以省略$element ['#type'] = 'html_tag';,系统会自动补全
$name用于批量渲染头部标签时在$element组成的更大的渲染数组中充当本元素的子元素名,开发者随意指定
我们可以在渲染数组中通过她设置任意头部标签,示例如下:
$renderArray['#attached']['html_head'][] = [
[
'#type' => 'html_tag', //如上所述,可省略该行,系统会自动补充
'#tag' => 'meta', //头部标签名
'#attributes' => [
'charset' => 'utf-8',
],
'#weight' => -1000,
],
'system_meta_content_type'
];
$renderArray['#attached']['html_head'][] = [
[
'#tag' => 'meta',
'#attributes' => [
'name' => 'viewport',
'content' => 'width=device-width, initial-scale=1.0',
],
],
'viewport'
];
这将产生以下标签:
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
头部link标签html_head_link:
html头部(head区域)的link标签,来自渲染数组$renderArray['#attached']['html_head_link'],是由$link构成的数组,$link格式如下:
$link = [$attributes, $should_add_header];
$attributes是一个属性集数组,构成link标签的属性,键名为属性名,键值为属性值
$should_add_header是一个布尔值,指示该link是否还需要添加到http响应头中,默认值为false
我们可以在渲染数组中通过她设置任意头部link标签,示例如下:
$renderArray['#attached']['html_head_link'][] = [
[
'rel' => 'shortcut icon',
'href' => '/core/misc/favicon.ico',
'type' => 'image/vnd.microsoft.icon',
],
false
];
将生成如下一个link标签:
<link rel="shortcut icon" href="/core/misc/favicon.ico" type="image/vnd.microsoft.icon" />
如果上面的$should_add_header指定为true时还会添加如下一条http响应头:
Link: < /core/misc/favicon.ico>; rel="shortcut icon"; type="image/vnd.microsoft.icon"
html_head_link是html_head的特殊情况
在系统最后$renderArray['#attached']['html_head_link']将被转化为$renderArray['#attached']['html_head']再处理
聚合源link标签feed:
聚合源(如果你对rss feed还不熟悉,请先搜索),来自渲染数组$renderArray['#attached']['feed'],是由$feed构成的数组,$feed格式如下:
$feed= [$href , $title];
$href是feed的连接
$title是标题,可选,默认为空字符串,该值应该是翻译后的值
示例如下:
$renderArray['#attached']['feed'][] = [
'http://www.yunke.com/rss.xml',
'yunke'
];
在html头部区域将产生如下一个link标签:
<link rel="alternate" type="application/rss+xml" title="yunke" href="http://www.yunke.com/rss.xml" />
feed是html_head_link的一种特殊情况
在系统最后$renderArray['#attached']['feed']将被转化为$renderArray['#attached']['html_head_link']再处理,feed不会产生http响应头
响应头http_header:
来自渲染数组$renderArray['#attached']['http_header'],是由$ header构成的数组,$ header格式如下:
$ header = [$name , $value , $replace];
$name是响应头的名字
$value是响应头的值
$replace是一个布尔值,true表示替换当前已设置的值,false表示将值追加到当前的值中,不设置默认为false
示例如下:
$renderArray ['#attached']['http_header'][] = ['X-Test-Teapot-Replace', 'This value gets replaced'];
$renderArray ['#attached']['http_header'][] = ['X-Test-Teapot-Replace', 'Teapot replaced', TRUE];
$renderArray ['#attached']['http_header'][] = ['X-Test-Teapot-No-Replace', 'This value is not replaced'];
$renderArray ['#attached']['http_header'][] = ['X-Test-Teapot-No-Replace', 'This one is added', FALSE];
$renderArray ['#attached']['http_header'][] = [' status', 404];
该选项也可以用于设置状态码或cookie,由于执行时期在系统派发响应事件时,因此优先级较高,如果你想要进行测试,请在控制器中执行以下代码:
$renderArray=['#markup' => "this is http_header test"];
$renderArray['#attached']['http_header'][] = ['X-Yunke', 'This is http_header value', FALSE];
return $renderArray;
可在火狐开发者工具中查看响应头,如下:
X-Yunke: This is http_header value
资源解析器:
该块内容较多,用独立主题阐述,请见本系列《资源解析器AssetResolver》
资源集css与js渲染器
资源解析器返回的资源是以选项数组表示的,详见本系列资源解析器主题,资源集渲染器主要工作是将该选项数组转换为渲染数组,并调整路径等
css资源集渲染器:
服务名:asset.css.collection_renderer
类:Drupal\Core\Asset\CssCollectionRenderer
js资源集渲染器:
服务名:asset.js.collection_renderer
类:Drupal\Core\Asset\JsCollectionRenderer
补充说明:
如果页面是ajax加载,那么以下位置将保存已加载数据:
$ajax_page_state = \Drupal::requestStack()->getCurrentRequest()->get('ajax_page_state');
比如$ajax_page_state['libraries']将保存已经加载的资源库
反馈互动