idci/asset-loader-bundle

Symfony2 扩展包,提供加载资源的功能

v2.2.0 2019-07-09 07:50 UTC

This package is auto-updated.

Last update: 2024-09-09 19:09:09 UTC


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