hiraeth / twig-tags
为Hiraeth Twig提供标签组件
Requires
- php: >=8.2
- hiraeth/app: ^3.0
- hiraeth/twig: ^3.0
- ivopetkov/html5-dom-document-php: ^2.0
Requires (Dev)
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^8.5
This package is auto-updated.
Last update: 2024-08-29 05:38:10 UTC
README
为Hiraeth Nano Framework中的Twig提供类似组件的标签。
介绍
这个包旨在解决一个问题,并且解决得很好。具体来说,它旨在使您能够创建和使用类似组件的模板。您可能想要这样做的主要原因之一是如果您正在使用像Tailwind这样的工具,并且想要避免编写传统的CSS类/选择器并依赖@apply
。现在可能的其他类似解决方案可能是编写非常重复且冗长的{% include %}标签。即使如此,也存在限制。例如,没有办法轻松地为父作用域中的特定包含组件提供子组件,因此您可能需要一组大量非常专业的组件,或者在单个包含组件中包含大量动态逻辑来处理提供给它的不同类型的数据。
为了解决这个问题,Twig Tags利用了Hiraeth 3.0 beta的新Renderer接口(用于Twig扩展)。这提供了对Twig模板的后处理修改。从Twig的角度来看,您的组件只是另一个HTML标签,但在您的模板渲染之后,后处理会使用类似React props的属性将这些标签替换为其相应的组件,从而提供一个完全上下文感知的解决方案。
问题
让我们想象一个简单的例子。您想制作一个按钮组件,以便可以在您的标记中添加按钮样式的链接。传统上,您只是使用标记
<a class="button" href="/route/to/resource">My Resource</a>
如果您有标准的CSS和类选择器,这相对是可以的。您可以在您的Twig模板中到处添加这些标记。然后如果您需要更新按钮的样式,只需进入您的CSS,找到.button
选择器,然后继续操作。
现在,Tailwind来了。您想使用Tailwind。所以,您的首选解决方案将是修改您的CSS以使用@apply
指令
.button { @apply <my tailwind classes here>; }
这行得通,但随着事情变得越来越复杂,您开始意识到@apply
并不总是像直接在元素上添加这些类那样工作。这很大程度上导致了Tailwind的创造者Adam Wathan写下“我可以绝对肯定,如果我从头开始重新创建Tailwind CSS,将没有@apply。”这也是为什么对@apply
的使用被强烈反对的原因。
好吧...没问题...让Twig来拯救。让我们将我们的按钮移动到自己的文件components/button.html
<a class="button" href="{{ href }}">{{ text }}</a>
...然后我们将使用如下所示的{% include ... %}
{% include 'components/button.html' with {href: "/route/to/resource", text: "My Resource"} %}
虽然这行得通,但存在很多缺点。首先,{% include %}
的语法非常冗长。其次,如果您有一个更复杂的组件,比如网格组件,其中网格中每个单元格的内容需要在父作用域中定义怎么办?如果您需要在组件中使用组件怎么办?您可以很容易地看出,您的日常开发体验将不再是通过相对简单解析HTML,而是一系列包含稀疏HTML、属性和条件来控制子元素类型,以及各种混乱的包含。
解决方案
为了展示Twig Tags的能力,让我们先安装它。
composer require hiraeth/twig-tags
现在我们将创建两个新的组件。首先resources/tags/atoms/title.html
<h2>{{ value }}</h2>
其次,一个网格(resources/tags/layout/grid.html
)
{% if title|default(null) %} <t:atoms:title value={% v: title %} /> {% endif %} <div class="grid grid-cols-12 grid-rows-none gap-4"> {% for child in children %} <div class="col-span-{{ 12 / split }}"> {{ child|raw }} </div> {% endfor %} </div>
注意,在上面的网格中,我们做了一些有趣的事情。
首先,我们包含了我们的 title
组件。组件可以轻松地包含子组件。其次,我们正在传递传入的动态 title
属性值。这种动态值的语法支持任何twig表达式。相应地,属性可以有对象值,也可以是任何有效的Twig表达式,例如:{% v: 2 * 2 %}
。
其次,我们在父作用域中循环原始子元素,以确定网格的内容,将每个子元素放置在适当的包装器中,并使用 col-span
,从而将Tailwind布局优雅地封装在组件中,而内容可以在其他地方定义。
最后,我们使用传入的 split
属性来动态确定 col-span
的值。传递 split="2"
将导致50/50的分割,每列跨越6列,而 split="4"
则会导致25/25/25/25的分割,每个项目跨越3列。
最后,让我们看看我们如何在主模板中使用我们的网格组件(以及扩展的标题组件)。
<t:layout:grid split="2" title="My Grid"> <p>First Child</p> <p>Second Child</p> </t:layout:grid>
很简单!
注意事项
好吧,总有一些。但我们承诺,没有多少。
- 您模板的扩展名必须是
.html
或.htm
,并且您的标签必须与包含它们的文件具有相同的扩展名。如果您使用的是Hiraeth,这可能已经是这种情况了,因为您不是异教徒。将来可能会支持其他格式,但当前它明确查找.html
或.htm
,并且标签组件扩展必须匹配模板扩展。 - 最后,由于HTML实际上不支持XML命名空间,您不能在
resources/tags
中直接有标签组件。它们 必须 在子目录中。当使用标签<t:layout:grid>
时,标签名的第一部分将被删除,其余部分将被转换为组件的路径。在这方面,<tag:layout:grid>
将同样工作...但如果有两个级别,第一部分将被删除,后处理器将无法将其识别为标签组件。
这就完了!
开发
代码检查和测试
运行分析
php vendor/bin/phpstan -l7 analyse src/
运行测试
php vendor/bin/phpunit --bootstrap vendor/autoload.php test/cases