光源/前端块

此包帮助将前端资源(HTML、JS、CSS)组合成可重用的块(模块)

4.1.2 2023-08-11 09:30 UTC

README

这是什么?

此包帮助将前端资源(HTML、CSS、JS)组合成可重用的块(模块)。

1. 优点
2. 如何使用
3. 块
4. 要求
5. 使用示例
6. 高级
7. 额外加载

优点

  • 允许将所有资源分组,简化编辑和代码阅读
  • 支持块之间的依赖关系,允许在一个块中使用另一个块,按照正确的顺序提供使用的块资源(CSS、JS)
  • 使用Twig作为模板引擎,对scss和webpack友好(见使用示例
  • 额外加载的包是微不足道的。有关详细信息,请参阅额外加载
  • 块可以放置在不同的文件夹中(例如,WordPress父主题和子主题)

如何使用

  1. 安装composer包

composer require lightsource/front-blocks

  1. 创建FrontBlocks实例
use LightSource\FrontBlocks\FrontBlocks;
use LightSource\FrontBlocks\Settings;
use LightSource\FrontBlocks\ExternalDependencies;

$settings = new Settings();
// namespace & folder of your blocks
$settings->addBlocksFolder('MyNamespace', 'AbsPathToMyFolder');
// optionally, your psr/container implementation for extra dependencies, see more information about this feature below
$container = null;
// optionally, your PSR-3 compatible logger, will be used when a twig template has syntax errors
$logger               = null;

$frontBlocks = new FrontBlocks($settings, $container, $logger);   
  1. 创建块
/Blocks
    Homepage
        Homepage.twig
        Homepage.css
        Homepage.php          

Homepage.php

// your block should extend the Block class
// (or implement \LightSource\FrontBlocks\Interfaces\BlockInterface, but only in case you need your own implementation)
class Homepage extends \LightSource\FrontBlocks\Block\Block
{
    protected string $title;

    public function loadById(int $id)
    {
        parent::load();

        // todo
        $this->title = 'Some title';
    }
}

Homepage.twig


<div class="homepage">{{ title }}</div>
  1. 渲染块,获取使用资源
// Block's creation with :
// a) automatic initialization of class's protected fields (for fields with built-in types or with the Block type)
// b) automatic passing external objects to block's constructors (where it needs)
$homepage = $frontBlocks->getCreator()->create(Homepage::class);
$homepage->loadById(1);

// rendering a target twig template with arguments (from the class's protected fields)
echo $frontBlocks->getRenderer()->render($homepage);

// reading & combining resources from used blocks by an extension (in the right order of rendering and with dependencies)
echo '<style>';
echo $frontBlocks->getRenderer()->getUsedResources('.css');
echo '</style>';

请参阅使用示例以获取更多信息。

块是PHP类及其附近的资源。

  • 静态资源
    如:模板(.twig)、CSS(.css、.scss、.min.css)、JS(js、min.js)、图片(.png)等...

  • 块类 - 为twig模板提供数据,管理依赖项

    • 所有受保护的字段都将用作twig模板的参数。
    • 受保护的字段可以是具有内置类型(字符串、整数、数组...)和其他块的字段,如果这些字段已声明类型,则它们将自动初始化为默认值(包括块字段,因此将自动创建声明类的一个实例)
    • 所有具有块类型的受保护字段都将标记为此块的所有依赖项
    • 可以有父子关系(因此每个块都可以扩展)

要求

  • php 7.4+
  • 块应具有与PSR-4兼容的命名空间和自动加载器
  • 资源名称应与块名称相同
  • 使用BEM方法不是必需的,但强烈推荐

使用示例

  1. 示例1 - 不使用scss和webpack
  2. 示例2 - 使用scss和webpack

高级

1. 加载器

该包具有加载器类,它获取块类列表,并为每个实例调用静态setup(?ContainerInterface $container)方法。如果您想为每个块添加一些监听器或执行其他任务,这将非常有用。例如,在WordPress中,您可以设置每个块的ajax监听器。

$frontBlocks->getLoader()->loadAllBlocks();

2. 外部依赖项(在自动创建过程中)

系统会自动创建内部块,这意味着它们应该有一个不带任何参数的构造函数,但有时你可能需要额外的依赖项,比如日志记录器或其他任何东西。在这种情况下,外部依赖项功能将有所帮助。FrontBlocks类有一个psr/ContainerInterface参数,你可以在其中提供任何实现(例如,php-di)。然后,在自动创建过程中,容器将为每个构造函数参数进行查询,并且其响应将自动传递给构造函数(通过类型比较,这是由于PHP反射功能实现的,所以依赖项的顺序或名称在这里并不重要)。

class MyBlock extends \LightSource\FrontBlocks\Block\Block
{
    private MyExtraClass $myExtraClass;

    // you can have any amount of dependencies, order is not important together with variable names
    // external dependencies are unique per block, so one block can have dependencies, others may not have
    public function __construct(MyExtraClass $variableWithAnyName)
    {
        parent::__construct();
        $this->myExtraClass = $variableWithAnyName;
    }
}

然后将依赖项传递到您的容器中

$dependency = new MyExtraClass();
// in this sample the php-di\php-di package is being using
$container = new \DI\Container();
$container->set(MyExtraClass::class, $dependency);
$frontBlocks = new FrontBlocks($settings, $container);

3. Twig 模板

  • 每个块都可用额外的键(_template_isLoaded_parentTemplate),在相关的Block调用load()方法后,_isLoaded将为true。
  • _merge过滤器(与标准合并不同,递归合并数组)
  • _include函数(blockArgs,additionalArgs),它使用额外的键进行块包含,因此你可以像这样包含块:{{ _include(blockName,{classes:['block-name',]} ),它将通过'_template'字段定位模板,并且只有当'_isLoaded'被设置时才会渲染。
  • 要扩展twig模板(显然php块类应该扩展父类) - 使用普通的twig方式,通过预定义的_parentTemplate变量,所以{% extends _parentTemplate %}

4. 块数组

支持带有块数组的字段,与块字段的方式相同,因此渲染过程中将自动为每个项调用getTemplateArgs(),这意味着你可以在twig模板中使用for循环并在每个项中使用_include(),而无需你进行额外的操作。

5. 复制块的工具

提供复制块(带名称替换)的工具
例如,在Blocks文件夹中,命令
{pathToComposer}/vendor/bin/fbf copy Source/Source.php Target/Target.php
将复制块及其所有兄弟文件,并进行名称替换,因此你可以创建一个示例块,并从中复制新的块。

6. 多态

PHP(7.4)不支持字段中的直接多态,所以很遗憾,你不能这样做

class Element {

}
class ElementThemeOrange extends Element {
 
}
class Wrapper {
 protected Element $element;
}
class WrapperThemeOrange extends Wrapper {
 protected ElementThemeOrange $element;
}

但是,这个包支持以下技巧

class Element {

}
class ElementThemeOrange extends Element {
 
}
class Wrapper {
 protected Element $element;
}
class WrapperThemeOrange extends Wrapper {
 public function __construct() {
  parent::__construct();
  
  $this->element = new ElementThemeOrange();
 }
}

在这种情况下,当使用创建器($wrapper = $frontBlocks->getCreator()->create(WrapperThemeOrange::class);)时,该包将正好选择ElementThemeOrange类。
(注意:**永远不要在构造函数中初始化内部块**,因为这个初始化只会用来获取类名,然后该字段将用新实例覆盖,该实例将使用创建器创建,否则外部依赖项功能将不可用。因此,不要在内部块的构造函数中设置任何值或调用任何方法,它不会有任何效果)

额外加载

对包的额外加载对Twig的影响不大,更多是依赖于Twig。以下是在4vCPU 16 RAM、SSD的实例上获得的粗略值。最终值将根据你的实例和使用的块而有所不同。

自动加载100个块(可选):9毫秒
渲染100个块 - 62毫秒
组合100个块的资源 - 3毫秒