我将Twig与Symfony2框架分开使用,将其分成更小的部分,以更好地满足我(感知到的)需求。我的框架的一部分是一个管理js/css依赖关系的资产管理库,经过预处理,组合,最小化,压缩,输出适当的<link>
和<script>
标签,放置在<head>
或<body>
的底部。
资产助手只有三个公共函数:require_asset($asset)
、render_head()
和render_bottom()
。第一个在不同的模板部分中很少使用(我希望将资产的加载保持在应用程序逻辑之外,因此在分支模板中)。其他两个需要在所有资产都被要求之后调用,并且(在资产管理器完成它的工作之后)返回要放置在模板中的适当的和标记。
所有普通模板都扩展基本模板:
base.twig:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{{ title }}</title>
<!--[if lt IE 9]><script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
{{ Assets.headAssets }}
</head>
</body>
{% block body %}
{% endblock %}
{{ Assets.bottomAssets }}
<body>
</html>
这里的{{ Assets.headAssets }}
和{{ Assets.bottomAssets }}
是通过之前声明的Twig全局变量Assets
调用前面提到的render_head()
和render_bottom()
方法;
在我的实例中,这个基本模板是从test.twig:
扩展而来的{% extends "base.twig" %}
{% import "forms.twig" as forms %}
{% block body %}
{{ Assets.requires('formtest.css') }}
{{ Assets.requires('testscript.js') }}
<form method="post">
{{ forms.form(form) }}
<input type="submit"/>
</form>
{% endblock %}
这里,{{ Assets.requires('formtest.css') }}
和{{ Assets.requires('testscript.js') }}
指示资产助手通过调用require_asset($asset)
来包含这个模板所需的css和js。
通常情况下,如果在分支之外完成,输出函数将在需要所有所需资产之后最后调用。
我遇到的问题与twig模板中这些函数的执行顺序有关。由于基地。首先调用Twig,并包含对输出函数的调用,这些函数在从扩展模板或包含的块/宏做出任何需求之前被调用。因此,结果是空的,没有考虑到这些新的要求。
我想到的解决这个问题的一种方法是在Twig返回渲染后计算输出,并在返回的结果中替换它们。这是可行的,但我觉得不够优雅。
我想知道是否有一种方法可以推迟{{ Assets.headAssets }}
和{{ Assets.bottomAssets }}
的执行,直到twig完成其他所有事情。我有什么办法做到这一点吗?
对于那些还在寻找答案的人,我写了一个允许延迟块渲染的Twig扩展
我想这样可以:
base.twig
{% set bodyContent %}
{% block body %}{% endblock body %}
{% endset %}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{{ title }}</title>
<!--[if lt IE 9]><script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
{{ Assets.headAssets }}
</head>
</body>
{{ bodyContent }}
{{ Assets.bottomAssets }}
<body>
</html>
其他文件可以不修改
正如你所看到的,block body
在base.twig
模板中首先调用,所以当执行{{ Assets.headAssets }}
调用时已经需要所有的资产。