performing/twig-components

Twig 组件扩展

0.6.0 2024-06-29 21:41 UTC

README

Latest Version on Packagist GitHub Tests Action Status Total Downloads

这是一个PHP包,用于自动创建以标签形式存在的Twig组件。这个包高度灵感来源于Laravel Blade组件。

安装

您可以通过Composer安装此包

composer require performing/twig-components

配置

此包应该可以在任何提供Twig的环境中运行。

/** @var \Twig\Environment $twig */

use Performing\TwigComponents\Configuration;

Configuration::make($twig)
    ->setTemplatesPath('/relative/directory/to/components')
    ->setTemplatesExtension('twig')
    ->useCustomTags()
    ->setup();

要启用此包,只需将您的Twig环境对象传递给函数,并指定相对于您的Twig模板文件夹的组件文件夹。

Craft CMS

在Craft CMS中,您应该这样做。

// Module.php
if (Craft::$app->request->getIsSiteRequest()) {    
    Event::on(
        Plugins::class,
        Plugins::EVENT_AFTER_LOAD_PLUGINS,
        function (Event $event) {
            $twig = Craft::$app->getView()->getTwig();
            \Performing\TwigComponents\Configuration::make($twig)
                ->setTemplatesPath('/components')
                ->useCustomTags()
                ->setup();
        }
    );
}

if语句确保您不会得到“无法注册扩展“...”因为扩展已经被初始化”的错误。

Symfony

在Symfony中,您可以这样做。

# services.yml

services:
    My\Namespace\TwigEnvironmentConfigurator:
        decorates: 'twig.configurator.environment'
        arguments: [ '@My\Namespace\TwigEnvironmentConfigurator.inner' ]
// TwigEnvironmentConfigurator.php

use Symfony\Bundle\TwigBundle\DependencyInjection\Configurator\EnvironmentConfigurator;
use Twig\Environment;
use Performing\TwigComponents\Configuration;

final class TwigEnvironmentConfigurator
{
    public function __construct(
        private EnvironmentConfigurator $decorated
    ) {}

    public function configure(Environment $environment) : void
    {
        $this->decorated->configure($environment);

        // Relative path to your components folder
        $relativePath = '_components'; 

        Configuration::make($environment)
            ->setTemplatesPath($relativePath)
            ->setTemplatesExtension('twig')
            ->useCustomTags()
            ->setup();
    }
}

用法

这些组件只是您选择的文件夹(例如components)中的Twig模板,可以在您的Twig模板中的任何位置使用。slot变量是在打开和关闭标签之间添加的任何内容。

{# /components/button.twig #}
<button>
    {{ slot }}
</button>

自定义语法

要访问组件,您需要使用自定义标签x后跟一个和组件的文件名。

{# /index.twig #}
{% x:button %}
    <strong>Click me</strong>
{% endx %}

您还可以像使用include一样传递任何参数。好处是您将拥有强大的attributes变量来合并属性或更改组件行为。

{# /components/button.twig #}
<button {{ attributes.merge({ class: 'rounded px-4' }) }}>
    {{ slot }}
</button>

{# /index.twig #}
{% x:button with {'class': 'text-white'} %}
    <strong>Click me</strong>
{% endx %}

{# Rendered #}
<button class="text-white rounded-md px-4 py-2">
    <strong>Click me</strong>
</button>

要访问位于子文件夹中的组件,您可以使用点表示法

{# /components/button/primary.twig #}
<button>
    {{ slot }}
</button>

{# /index.twig #}
{% x:button.primary %}
    <strong>Click me</strong>
{% endx %}

HTML语法

可以使用特殊的HTML语法获得相同的行为。之前的组件示例也可以用这种方式使用。

{# /index.twig #}
<x-button class='bg-blue-600'>
    <span class="text-lg">Click here!</span>
</x-button>

命名槽

{# /components/card.twig #}
<div {{ attributes.class('bg-white shadow p-3 rounded') }}>
    <h2 {{ title.attributes.class('font-bold') }}>
        {{ title }}
    </h2>
    <div>
        {{ body }}
    </div>
</div>

{# /index.twig #}
<x-card>
    <x-slot name="title" class="text-2xl">title</x-slot>
    <x-slot name="body">Body text</x-slot>
</x-card>

也可以使用标准语法。

{# /index.twig #}
{% x:card %}
    {% slot:title with {class: "text-2xl"} %}
        Title
    {% endslot %}
    {% slot:body %}
        Title
    {% endslot %}
{% endx %}

属性

您可以通过不同的方式将任何属性传递给组件。要将内容解释为Twig,您需要在属性名称前添加一个,但它也可以以其他方式工作。

<x-button 
    :any="'evaluate' ~ 'twig'"
    other="{{'this' ~ 'works' ~ 'too'}}" 
    another="or this"
    this="{{'this' ~ 'does'}}{{ 'not work' }}"
>
    Submit
</x-button>

Twig命名空间

除了指定的目录外,您还可以通过在组件名称前添加命名空间和一个来从Twig命名空间引用组件。命名空间定义如下

// register namespace with twig template loader
$loader->addPath(__DIR__ . '/some/other/dir', 'ns');

组件可以使用以下方式包含

{% x:ns:button with {class:'bg-blue-600'} %}
    <span class="text-lg">Click here!</span>
{% endx %}

{# or #}

<x-ns:button class='bg-blue-600'>
    <span class="text-lg">Click here!</span>
</x-ns:button>

动态组件

有时您可能需要渲染一个组件,但直到运行时都不知道应该渲染哪个组件。在这种情况下,您可以使用内置的动态-component组件根据运行时值或变量渲染组件。

{% set componentName = 'button' %}
<x-dynamic-component :component="componentName" class='bg-blue-600'>
    <span class="text-lg">Click here!</span>
</x-dynamic-component>

贡献

欢迎拉取请求。对于重大更改,请首先打开一个问题来讨论您想要更改的内容。

请确保根据需要更新测试。

测试

composer test

许可证

MIT许可证(MIT)。有关更多信息,请参阅许可证文件