Добавить параметр в функцию addJS
, который указывает позицию на странице.По умолчанию у вас должна быть поддержка как минимум head
и foot
(head
поместит его в голову, foot
поместит его прямо перед закрытием </body>
).
public function addJS($string, $position = 'head') {
if (!is_array($this->js[$position])) {
$this->js[$position] = array($string);
} elseif (!in_array($string, $this->js[$position])) {
$this->js[$position][] = $string;
}
}
Затем включите токены в шаблон, чтобы указать позиции:
{{js_head}}
</head>
<body>
<!--content here-->
{{js_foot}}
</body>
Затем при рендеринге просто сделайте что-то вроде:
$js = $this->js;
$positions = preg_replace_callback(
'/{{js_(inline_)?([a-zA-Z0-9]+)}}/',
function ($match) use ($js) {
if (isset($js[$match[2]])) {
$js = implode("\n", $js[$match[2]]);
if ($match[1] == 'inline') {
return $js;
} else {
return '<script type="text/javascript">'.$js.'</script>';
}
return '';
},
$templateBody
);
Сейчасреальное преимущество заключается в том, что ваши шаблоны могут четко и тривиально определять свои собственные позиции для повторно используемых и часто используемых битов:
$this->addJS('return this.form.submit();', 'submit_form');
$html = '
<input type="text" onblur="{{js_inline_submit_form}}" />
<button name="submit" onclick="{{js_inline_submit_form}}" />
';
Это может быть весьма полезным, поскольку теперь вы не дублируете вызовы JS вездев вашем коде.Кроме того, это сократит издержки, связанные с переносом каждого вывода в теги <script>
(поскольку он охватывает всю позицию в тегах, а не каждый фрагмент содержимого) ...
Это позволит вам затем взять все не встроенные файлы JS и скомпилировать серию файлов во время выполнения для отправки в браузер, чтобы позаботиться о кэшировании.Это добавляет преимущество, заключающееся в том, что вы можете сохранять свой JS близким к вашим представлениям (для удобства обслуживания), при этом все еще обслуживая кэшированный JS, и не нужно повторно отправлять его каждый раз ...
public function buildJSCache($position) {
if (!isset($this->js[$position]) || empty($this->js[$position])) {
return '';
}
$file = implode($this->js[$position]);
$name = 'js/'.md5($file) .'.js';
if (!file_exists($name)) {
file_put_contents($name, $file);
}
return $name;
}
Затем в вашемкод шаблона, просто сделайте:
$replace = $this->buildJSCache('head');
if ($replace) {
$replace = '<script type="text/javascript" src="'.$filename.'"></script>';
}
$template = str_replace('{{js_head}}', $replace, $template);
Вы получаете двойной выигрыш в удобстве обслуживания и скорости (вы даже можете уменьшить его, если хотите).