webflorist / htmlfactory
Laravel 的便捷且强大的 HTML 构建器
Requires
- laravel/framework: >=5.5 <10.0.0
Requires (Dev)
- ext-dom: *
- gajus/dindent: ^2.0
- orchestra/testbench: >=3.5
README
Laravel (>=v5.5) 的便捷且强大的 HTML 构建器
描述
此软件包提供了在 Laravel 中构建 HTML 的功能,无需编写任何 HTML。
此软件包允许您
- 使用所有相关 HTML 元素的静态工厂方法。
- 通过流畅的方法调用链设置 HTML 属性(对当前元素有效)。
- 充分利用 IDE 的好处(自动完成)。
- 使用
Decorator
类为特定前端框架设置输出样式 - 保持视图的前端无关性。
- 使用
Decorators
和Components
扩展其功能。 - 生成符合无障碍规范的 HTML 5 输出。
此软件包用作 webflorist/formfactory 的基础。如果您想在 Laravel 中轻松创建表单,请查看此软件包。
安装
- 通过 composer 需求此软件包:
composer require webflorist/htmlfactory
- 发布配置:
php artisan vendor:publish --provider="Webflorist\HtmlFactory\HtmlFactoryServiceProvider"
- 在新发布的配置文件(位于
app/config/htmlfactory.php
)中设置decorators
配置。
请注意,此软件包配置为自动发现 Laravel。因此,软件包的 Service Provider Webflorist\HtmlFactory\HtmlFactoryServiceProvider
和 Html
Facade Webflorist\HtmlFactory\HtmlFactoryFacade
将自动注册到 Laravel 中。
配置
可以通过 config/htmlfactory.php
配置软件包。目前只有一个设置
decorators
:设置应加载的装饰器分组 ID。结果,所有相应的装饰器都将应用于生成的 HTML 元素(例如,'bootstrap:v3')。
基本概念
以下是此软件包基本概念的定义,以便更好地理解本文档
请注意,每当本文档使用术语 Element
时,它还包括 Component
类(除非另有说明),因为它们在技术上也是 Element
类。
用法
使用 Html-
外观或简单实例化相应的 Element
或 Component
类生成 HTML 元素或组件。
由于此软件包是以 IDE 友好的方式构建的,因此您只需在您的自动完成 IDE 中键入 Html::
,就应该立即获得可用元素以及包含的组件的列表。(当然,此自动完成不会与您的自己的组件一起工作。)
使用 generate()
方法生成最终 HTML 字符串。但是,由于 HtmlFactory 包的 Element
类包含一个执行此操作的魔法 __toString()
方法,因此在 blade 模板中使用 Html 外观时可以省略 generate()
方法。
基本示例
以下是从 Laravel-blade 模板中生成 div
元素的一个非常基本的示例
Blade Code:
-----------
{!! Html::div() !!}
Generated HTML:
---------------
<div></div>
使用流畅方法修改元素
可以通过链式调用Element的各种流畅方法来进一步修改(例如添加HTML属性或内容)。在您的自动完成功能下,您只需输入例如Html::div()->
,就应该立即得到该元素可用的方法列表。以下是提供的方法概览
添加HTML属性
现在假设,我们想要给Element添加一些HTML属性
- 一个值为
myId
的id
属性 - 一个值为
bar
的data-attributedata-foo
- 一个名为
myClass
的class
我们可以通过应用这些修改的相应方法来实现这一点
Blade Code:
-----------
{!! Html::div()
->id('myId')
->data('foo','bar')
->addClass('myClass')
!!}
Generated HTML:
---------------
<div id="myId" data-foo="bar" class="myClass">
<span>Hello world!</span>
</div>
一般来说,设置HTML属性的方法的名称与它们的名称相同(例如,可以使用id()
方法设置id
属性)。以下是一些例外
- 包含连字符(例如
accept-charset
)的属性的setter方法与驼峰式命名的属性名称相同(例如acceptCharset()
)。 - 具有多个值的属性具有以
add
为前缀(并采用驼峰式)的相应方法。一个例子是,对于上面示例中使用的class
属性,有addClass()
。 data
-属性通过data()
方法设置,该方法将数据属性的后缀作为它的第一个参数,将值作为它的第二个参数(如上面的示例所示)。
请注意,由于该包旨在仅输出有效的HTML,因此可用的方法因元素而异。例如,您不能在div元素上使用selected()
方法,因为根据HTML标准,这是不允许的。
所有HTML属性的值也可以是闭包。闭包将Element对象本身作为它的唯一参数来处理。以下是一个示例
Blade Code:
-----------
{!! Html::div()
->id('myId')
->title(
function ($element) {
return "This div's id is ".$element->attributes->id;
}
)
!!}
Generated HTML:
---------------
<div id="myId" title="The ID of this div is myId"></div>
添加Vue指令
除了标准的HTML属性外,您还可以通过相应的元素方法设置所有可能的Vue指令(请参阅Vue指令)
此外,还提供了最常见的DOM事件的vOn()
的快捷方法
添加内容
当然,ContainerElement也可以有内容。让我们看看这个示例
Blade Code:
-----------
{!! Html::div()
->content([
Html::span()->content('Hello world!'),
"What's up?"
])
!!}
Generated HTML:
---------------
<div>
<span>Hello world!</span>
What's up?
</div>
content()
方法接受一个子元素或子元素的数组作为其参数。子元素可以是另一个Element
对象或简单的文本字符串。还有额外的prependContent()
和appendContent()
方法,它们在现有内容之前或之后添加内容。以下是所有内容相关方法的概览
在Element之前或之后插入一个兄弟元素
以下方法允许您在Element之前或之后插入一个兄弟元素(无论是纯文本还是另一个Element
)。
将一个元素包裹在另一个元素中。
您还可以将包装器应用到元素上。请看这个示例
Blade Code:
-----------
{!! Html::div()
->id('myDivElement')
->wrap(
Html::div()->addClass('wrapper')
)
!!}
Generated HTML:
---------------
<div class="wrapper">
<div id="myDivElement"></div>
</div>
应用Blade视图以渲染元素
您还可以使用view()
方法将Blade视图应用到元素上。元素本身在视图中作为$el
可用。要渲染它,请调用$el->renderHtml()
。
以下是一个示例
Blade Code:
-----------
{!! Html::div()
->content('Hello World!')
->view('my-view')
!!}
my-view.blade.php:
-----------
<div class="my-view-wrapper">
before element
{!! $el->renderHtml() !!}
after element
</div>
Generated HTML:
---------------
<div class="my-view-wrapper">
before element
<div>Hello World!</div>
after element
</div>
闭包装饰器
有时您可能希望对单个元素应用一些复杂的装饰,或者影响全局装饰器类(请参阅以下说明)应用后的Element。您可以使用Element方法decorate()
来做到这一点。该方法接受一个闭包作为其唯一参数,该闭包将Element本身作为其唯一属性传递
请看这个示例
Blade Code:
-----------
{!! Html::div()
->id('myId')
->data('foo','bar')
->content(
Html::span()->content('Hello world!')
)
->wrap(
Html::div()->addClass('wrapper')
)
->decorate( function($element) {
$element
->id('myDecoratedId')
->data('decorated-foo','decorated-bar')
->appendContent("What's up?");
$element->wrapper->addClass('decoratedWrapper');
})
!!}
Generated HTML:
---------------
<div class="wrapper decoratedWrapper">
<div id="myDecoratedId" data-foo="bar" data-decorated-foor="decorated-bar">
<span>Hello world!</span>
What's up?
</div>
</div>
可扩展性
组件
在某些情况下,您可能希望快速创建更复杂的HTML元素,这些元素已经预先设置了某些属性、内容或包装器,提供了额外的功能,甚至需要某些构造参数。您还可能希望通过Html
外观(例如,通过Html::myCustomComponent()
)访问此组件。所有这些都可以通过创建Components
来实现。
组件基本上是一个类,它扩展了 Element
类之一或另一个 Component
类。在 Components
文件夹中已经包含了一些组件。这些包括 InputElement
的扩展以及 ButtonElement
,为可能的 '类型' 提供组件。
组件注册
要使用 Html
表面创建组件,必须满足以下条件:
- 组件必须实现
RegisteredComponentInterface
,强制存在静态的getAccessor()
方法,该方法应返回一个方法名,通过这个方法名可以通过Html
表面创建该组件。 - 组件必须注册到
HtmlFactory
服务。
注册可以通过以下方法之一完成:
- 注册一个单个(完全限定)类名作为组件。
app(Webflorist\HtmlFactory\HtmlFactory::class)->components->register(string $className, bool $force = false)
示例app(Webflorist\HtmlFactory\HtmlFactory::class)->components->register('FQCN\Of\My\AwesomeComponent')
- 从目录中的文件注册组件。
app(Webflorist\HtmlFactory\HtmlFactory::class)->components->registerFromFolder(string $namespace, string $folder, bool $force = false):
示例app(Webflorist\HtmlFactory\HtmlFactory::class)->components->registerFromFolder('Fully\Qualified\Namespace','/path/to/my/awesome_components'):
关于 $force
参数:通常,如果另一个组件已使用相同的访问器安装,HtmlFactory 将抛出错误。可以通过将 $force
设置为 true 来规避这种情况。(这样也可以覆盖包含的组件。)
执行这些注册的最佳位置是在你的 AppServiceProvider
的 boot()
方法中(或任何其他 ServiceProvider)。
请注意,如果你不打算通过 Html
表面使其可实例化(例如,如果你使用自己的 Service/Facade 或使用 new
关键字实例化对象),则不需要实现 RegisteredComponentInterface
或注册组件。
自定义组件。
要自定义你的组件,你可以实现以下钩子方法
(确保在覆盖这些方法时也调用父方法,特别是在扩展其他组件时,以确保不丢失任何功能。)
当然,你也可以创建自己的构造函数(例如,添加必需的参数)。只需确保调用父构造函数。
当然,你还可以添加额外的流畅设置器,以便在视图中调用组件。该包已包括一些特质,它们提供了一些通用的流畅设置器和相应的属性。您可以在命名空间 Webflorist\HtmlFactory\Components\Traits
中找到它们。
示例
让我们以包含的 SubmitButtonComponent
作为一个非常基本的示例
namespace Webflorist\HtmlFactory\Components; use Webflorist\HtmlFactory\Components\Contracts\RegisteredComponentInterface; use Webflorist\HtmlFactory\Elements\ButtonElement; class SubmitButtonComponent extends ButtonElement implements RegisteredComponentInterface { protected function setUp() { parent::setUp(); $this->type('submit'); } static function getAccessor(): string { return 'submitButton'; } }
该组件实现了 setUp()
方法,将属性 type
设置为默认值 submit
。此外,它还实现了 RegisteredComponentInterface
并将 submitButton
定义为其访问器。(此外,所有包含的组件都在 HtmlFactoryServiceProvider
的 boot
方法中注册。)
这使以下用法成为可能
Blade Code:
-----------
{!! Html::submitButton() !!}
Generated HTML:
---------------
<button type="submit"></button>
因此,Html::submitButton()
的输出与 Html::button()->type('submit')
相同。
查看其他包含的组件以获取更多示例!
装饰器
自定义 HtmlFactory 输出的第二种方法是使用装饰器。装饰器是定义了它们可以处理哪些 Elements 的类。例如,你可以创建一个装饰器,它将 CSS 类添加到所有 ButtonElements。装饰器也是应用前端框架特定修改(例如,当使用 bootstrap 作为前端框架时,将 form-control
类添加到字段元素)的绝佳方式。装饰器本身还可以声明一个组-ID,这意味着只有当其组-ID 出现在 decorators
配置字符串中时,装饰器才会应用。
装饰器必须扩展抽象类 Webflorist\HtmlFactory\Decorators\Abstracts\Decorator
,强制实现以下抽象方法
注册装饰器
装饰器必须使用以下方法之一注册到 HtmlFactory 服务:
- 注册一个单个(完全限定)类名作为装饰器。
app(Webflorist\HtmlFactory\HtmlFactory::class)->decorators->register(string $className)
示例app(Webflorist\HtmlFactory\HtmlFactory::class)->decorators->register('FQCN\Of\My\AwesomeDecorator')
- 从目录中的文件注册装饰器。
app(Webflorist\HtmlFactory\HtmlFactory::class)->decorators->registerFromFolder(string $namespace, string $folder):
示例app(Webflorist\HtmlFactory\HtmlFactory::class)->decorators->registerFromFolder('Fully\Qualified\Namespace','/path/to/my/awesome_decorators'):
与组件一样,执行这些注册的最佳位置是在你的 AppServiceProvider
的 boot()
方法中(或任何其他 ServiceProvider)。
示例
HtmlFactory已经包含了一些内置装饰器。让我们来看看DecorateButtonElement
类
use Webflorist\HtmlFactory\Decorators\Abstracts\Decorator; use Webflorist\HtmlFactory\Elements\ButtonElement; class DecorateButtonElement extends Decorator { public static function getGroupId() { return 'bootstrap:v3'; } public static function getSupportedElements(): array { return [ ButtonElement::class ]; } public function decorate() { $this->element->addClass('btn'); } }
其功能相当明显。只有当当前配置htmlfactory.decorators
中存在'bootstrap:3'时,装饰器才会被应用。此外,它只应用于与Webflorist\HtmlFactory\Elements\ButtonElement
相同或为其后代的元素或组件。其功能是向按钮添加特定的Bootstrap CSS类'btn'。
查看其他内置装饰器以获取更多示例!