创建 UX 捆绑包
提示
在阅读本文之前,您可能需要查看 可重用捆绑包的最佳实践。
这里有一些技巧使您的捆绑包安装为 UX 捆绑包。
资源位置
您的资源必须位于以下目录之一,并包含 package.json
文件,以便 Flex 可以在安装/更新期间处理它
/assets
(推荐)/Resources/assets
/src/Resources/assets
package.json 文件
您的 package.json
文件必须包含带有已定义控制器的 symfony
配置,并且还需要将必需的包添加到 peerDependencies
和 importmap
(importmap 中的包列表应与 peerDependencies 中的包列表相同)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
{
"name": "@acme/feature",
"version": "1.0.0",
"symfony": {
"controllers": {
"slug": {
"main": "dist/controller.js",
"fetch": "eager",
"enabled": true,
"autoimport": {
"@acme/feature/dist/bootstrap4-theme.css": false,
"@acme/feature/dist/bootstrap5-theme.css": true
}
}
},
"importmap": {
"@hotwired/stimulus": "^3.0.0",
"slugify": "^1.6.5"
}
},
"peerDependencies": {
"@hotwired/stimulus": "^3.0.0",
"slugify": "^1.6.5"
}
}
在这种情况下,位于 [assets directory]/dist/controller.js
的文件将被公开。
提示
您可以直接在此 dist/controller.js
文件中编写原始 JS,或者您可以使用 TypeScript 编写控制器并将其转换为 JavaScript。
这是一个示例
将以下内容添加到您的
package.json
文件1 2 3 4 5 6 7 8 9 10 11 12 13 14
{ "scripts": { "build": "babel src --extensions .ts -d dist" }, "devDependencies": { "@babel/cli": "^7.20.7", "@babel/core": "^7.20.12", "@babel/plugin-proposal-class-properties": "^7.18.6", "@babel/preset-env": "^7.20.2", "@babel/preset-typescript": "^7.18.6", "@hotwired/stimulus": "^3.2.1", "typescript": "^4.9.5" } }
将以下内容添加到您的
babel.config.js
文件 (应位于您的package.json
文件旁边)1 2 3 4 5 6 7 8 9 10 11 12
module.exports = { presets: [ ['@babel/preset-env', { "loose": true, "modules": false }], ['@babel/preset-typescript', { allowDeclareFields: true }] ], assumptions: { superIsCallableConstructor: false, }, };
- 运行
npm install
安装新的依赖项。 - 使用 TypeScript 在
src/controller.ts
中编写您的 Stimulus 控制器。 - 运行
npm run build
将您的 TypeScript 控制器转换为 JavaScript。
要在模板中使用您的控制器 (例如,在您的捆绑包中定义的模板),您可以像这样使用它
1 2 3 4 5 6 7 8 9 10
<div
{{ stimulus_controller('acme/feature/slug', { modal: 'my-value' }) }}
{#
will render:
data-controller="acme--feature--slug"
data-acme--feature--slug-modal-value="my-value"
#}
>
...
</div>
不要忘记添加 symfony/stimulus-bundle:^2.9
作为 composer 依赖项,以使用 Twig stimulus_*
函数。
提示
控制器命名:在此示例中,PHP 包的名称为 acme/feature
,package.json
中控制器的名称为 slug
。因此,Stimulus 的完整控制器名称将为 acme--feature--slug
,但使用 stimulus_controller()
函数,您可以使用 acme/feature/slug
。
每个控制器在 package.json
文件中都有许多选项
已启用
:- 控制器是否应默认启用。
主文件
:- 控制器文件的路径。
获取方式
:- 页面加载时如何包含控制器和依赖项。使用
eager
(默认) 将控制器和依赖项包含在页面加载时下载的 JavaScript 中。使用lazy
将控制器和依赖项隔离到单独的文件中,并且仅在 data-controller HTML 出现在页面上时异步下载。 自动导入
:- 要与控制器一起导入的文件列表。例如,当有多种 CSS 样式取决于所使用的前端框架时(例如 Bootstrap 4 或 5,Tailwind CSS...)很有用。该值必须是一个对象,其中文件作为键,布尔值作为每个文件的值,以设置是否应导入该文件。
Asset Mapper 的具体说明
要使您的捆绑包的资源与 AssetMapper 一起使用,您必须在 package.json
文件中添加如上的 importmap
配置,并在容器中预置一些配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
namespace Acme\FeatureBundle;
use Symfony\Component\AssetMapper\AssetMapperInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
class AcmeFeatureBundle extends AbstractBundle
{
public function prependExtension(ContainerConfigurator $configurator, ContainerBuilder $container): void
{
if (!$this->isAssetMapperAvailable($container)) {
return;
}
$container->prependExtensionConfig('framework', [
'asset_mapper' => [
'paths' => [
__DIR__ . '/../assets/dist' => '@acme/feature-bundle',
],
],
]);
}
private function isAssetMapperAvailable(ContainerBuilder $container): bool
{
if (!interface_exists(AssetMapperInterface::class)) {
return false;
}
// check that FrameworkBundle 6.3 or higher is installed
$bundlesMetadata = $container->getParameter('kernel.bundles_metadata');
if (!isset($bundlesMetadata['FrameworkBundle'])) {
return false;
}
return is_file($bundlesMetadata['FrameworkBundle']['path'] . '/Resources/config/asset_mapper.php');
}
}