idci / asset-loader-bundle
Symfony2 扩展包,提供加载资源的功能
Requires
- php: ^7.1.3
- symfony/config: ~4.2
- symfony/dependency-injection: ~4.2
- symfony/event-dispatcher: ~4.2
- symfony/http-foundation: ~4.2
- symfony/http-kernel: ~4.2
- twig/twig: ~1.34|~2.4
Requires (Dev)
- phpunit/phpunit: ~5.7
- symfony/framework-bundle: ~4.2
- symfony/twig-bundle: ~4.2
README
介绍
在使用 Symfony 2(或 3)框架时,我们发现加载自定义表单类型小部件的资产很麻烦。一个经常出现的问题是加载嵌入到小部件中的前端依赖项。
问题 1 - 依赖项顺序
假设你想创建一个表单类型,它是文本表单类型的子类,其小部件将使输入类型文本的背景着色;一旦输入为空。你的小部件将看起来像这样
Form/fields.html.twig
{%- block colored_text_widget -%} <div class="colored"> {{- form_widget(form) -}} </div> <style> .colored input[type="text"] { border-color: #c9302c, background-color: #f3d9d9 } </style> <script type="text/javascript"> $(document).on('change', '.colored input[type="text"]', function () { if ($input.val()) { $input.css({ 'border-color': '#cccccc', 'background-color': '#ffffff' }); } else { $input.css({ 'border-color': '#c9302c', 'background-color': '#f3d9d9' }); } }); </script> {%- endblock -%}
如你所见,此 JavaScript 代码需要 jQuery。当此脚本执行时,jQuery 将不可用(除非你在 html 文档的头部放置 jQuery 脚本,但我们不希望这样做)
一个可能的解决方案是将此代码包裹在以下纯函数中
window.addEventListener('load', function () { // code goes here ... });
这样,当代码执行时,Jquery 应该已经准备好了可以使用。但如果你的小部件基于整个库呢?
问题 2 - 依赖项重复
给定与上面示例相同的表单类型,如果你有一个在你的 Web 应用程序中渲染此表单 3 次的页面,你将在 DOM 中重复 3 次你的脚本和样式表。你只需要一次。
此包试图解决这些问题。
安装
在你的 composer.json
文件中添加依赖项
"require": { ... "idci/asset-loader-bundle": "dev-master" },
使用 composer 在你的应用程序中安装这些新依赖项
$ php composer.phar update
或使用 docker 和 docker-compose
$ make composer-update
在你的应用程序内核中注册所需的扩展包
<?php // app/AppKernel.php public function registerBundles() { $bundles = array( // ... new IDCI\Bundle\AssetLoaderBundle\IDCIAssetLoaderBundle(), ); }
如果你想要激活加载你的资产自动的订阅者(更多关于此的信息稍后提供,在你的 config.yml 文件中添加以下内容。
# app/config/config.yml idci_asset_loader: providers: load_all: true
使用方法
资产声明
将资产添加到你的表单类型中非常简单
- 你的 AbstractType 必须实现来自 AssetProviderInterface 接口的方法 getAssetCollection。The getAssetCollection 包含一个资产对象的数组。
- 你必须将你的类型定义为服务,并添加名为 idci_asset_loader.asset_provider 的标签。
在下面的示例中,我们从一个表单类型中加载资产。资产提供者不一定是表单类型,任何服务都可以完成这项工作。
AbstractType
namespace MyBundle/Form/Type; use IDCI\Bundle\AssetLoaderBundle\AssetProvider\AssetProviderInterface; use IDCI\Bundle\AssetLoaderBundle\Model\Asset; use IDCI\Bundle\AssetLoaderBundle\Model\AssetCollection; class MyType extends AbstractType implements AssetProviderInterface { /** * @var AssetCollection */ private $assetCollection; /** * Constructor */ public function __construct() { $this->assetCollection = new AssetCollection(); } /** * {@inheritDoc} */ public function getAssetCollection() { return $this->assetCollection; } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $this->assetCollection->add(new Asset('MyBundle:Form:form_type_asset.html.twig', $options)); ... return $view->vars; } .... }
如果你有多个资产,这些资产必须按照可预测的顺序加载,你可以为资产添加一个优先级(默认为 -1)。优先级越高,它将在 DOM 中越早加载。
$this->assetCollection->add(new Asset('MyBundle:Form:form_type_asset_1.html.twig', array(), 0)); $this->assetCollection->add(new Asset('MyBundle:Form:form_type_asset_2.html.twig', array( 'options' => $options, 'form' => $view ), 1));
Services.yml
services: my_type: class: MyBundle\Form\Type\MyType tags: - { name: form.type, alias: my_type } - { name: idci_asset_loader.asset_provider, alias: my_type }
手动加载你的资产
你可以使用 idci_asset_loader.asset_dom_loader 服务来为单个或所有提供者加载资产。这将注册一个订阅者,该订阅者在内核响应时将资产追加到 DOM(在 body 的末尾)。
<?php // Load assets from all providers $this->get('idci_asset_loader.asset_dom_loader')->loadAll(); // Load assets from one provider $this->get('idci_asset_loader.asset_dom_loader')->load('my_type');
自动加载你的资产
在大多数情况下,你只想让订阅者为你加载所有资产。要加载所有提供者的所有资产
# app/config/config.yml idci_asset_loader: providers: load_all: true
你也可以加载一些特定的提供者。如果 load_all 设置为 true,以下内容将没有任何影响。
# app/config/config.yml idci_asset_loader: providers: load_only: - my_provider_service_alias_1 - my_provider_service_alias_2 # - ...
测试
运行测试
$ php ./vendor/bin/phpunit --coverage-text
或使用 docker 和 docker-compose
$ make phpunit