StimulusBundle:Symfony 与 Stimulus 的集成
提示
在 http://ux.symfony.ac.cn 查看 Symfony UX 的实时演示!
此扩展包添加了 Symfony、Stimulus 和 Symfony UX 包之间的集成
- Twig
stimulus_
函数和过滤器,用于在模板中添加 Stimulus 控制器、 - 操作和目标;
- Twig
- 集成加载 UX 包(额外的 Stimulus 控制器)
安装
首先,如果您还没有资源处理系统,请选择并安装一个;两者都与 StimulusBundle 配合良好
- AssetMapper:基于 PHP 的资源处理系统
或
- Webpack Encore 基于 Node 的打包系统
请参阅 Encore 与 AssetMapper,了解哪一个最适合您的项目。
接下来,安装扩展包
1
$ composer require symfony/stimulus-bundle
如果您正在使用 Symfony Flex,那就完成了!配方将更新必要的文件。如果不是,或者您感到好奇,请参阅手动设置。
提示
如果您正在使用 Encore,请务必安装您的资源(例如 npm install
)并重启 Encore。
用法
现在您可以在 assets/controllers
目录中创建自定义 Stimulus 控制器。实际上,您应该已经有一个示例控制器在那里了:hello_controller.js
1 2 3 4 5 6 7
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
connect() {
this.element.textContent = 'Hello Stimulus! Edit me in assets/controllers/hello_controller.js';
}
}
然后,在您的 HTML 中激活控制器
1 2 3
<div data-controller="hello">
...
</div>
可选地,此扩展包有一个 Twig 函数来渲染属性
1 2 3 4 5 6 7 8
<div {{ stimulus_controller('hello') }}>
...
</div>
<!-- would render -->
<div data-controller="hello">
...
</div>
就是这样!每当此元素出现在页面上时,hello
控制器将被激活。
关于 Stimulus 还有很多要学习的。请参阅 Stimulus 文档了解所有详细信息。
TypeScript 控制器
如果您想使用 TypeScript 定义您的控制器,您可以这样做!安装并设置 sensiolabs/typescript-bundle。然后确保将 assets/controllers
路径添加到 sensiolabs_typescript.source_dir
配置中。最后,在该目录中创建您的控制器,您就可以开始了。
UX 包
Symfony 提供了一组 UX 包,这些包添加了额外的 Stimulus 控制器来解决常见问题。StimulusBundle 会激活您的 assets/controllers.json
文件中提到的任何第三方 Stimulus 控制器。每当您安装 UX 包时,此文件都会更新。
官方 UX 包有:
- ux-autocomplete:将
EntityType
、ChoiceType
或 *任何*<select>
元素转换为由 Ajax 驱动的自动完成字段(查看演示) - ux-chartjs:使用 Chart.js 轻松创建图表(查看演示)
- ux-cropperjs:用于裁剪图像的表单类型和工具(查看演示)
- ux-dropzone:用于文件上传的风格化“拖放区”表单类型(查看演示)
- ux-lazy-image:使用 BlurHash 优化图像加载(查看演示)
- ux-live-component:使用零 JavaScript 构建动态界面(查看演示)
- ux-notify:使用 Mercure 发送服务器发送的原生通知(查看演示)
- ux-react:从 Twig 渲染 React 组件(查看演示)
- ux-svelte:从 Twig 渲染 Svelte 组件(查看演示)
- ux-swup:与 Swup 集成(查看演示)
- ux-toggle-password:切换密码输入字段的可见性(查看演示)
- ux-translator:在 JavaScript 中使用您的 Symfony 翻译(查看演示)
- ux-turbo:与 Turbo Drive 集成,实现单页应用体验(查看演示)
- ux-twig-component:构建由 PHP 类支持的 Twig 组件(查看演示)
- ux-typed:与 Typed 集成(查看演示)
- ux-vue:从 Twig 渲染 Vue 组件(查看演示)
延迟加载 Stimulus 控制器
默认情况下,您的所有控制器(即 assets/controllers/
中的文件 + assets/controllers.json
中的控制器)将在每个页面上下载和加载。
有时您可能有一个控制器仅在某些页面上使用。在这种情况下,您可以将控制器设置为“延迟加载”。在这种情况下,它不会在初始页面加载时下载。相反,一旦页面上出现与控制器匹配的元素(例如 <div data-controller="hello">
),控制器及其导入的任何其他内容将通过 Ajax 延迟加载。
要使您的自定义控制器之一延迟加载,请在顶部添加一个特殊注释
1 2 3 4 5 6
import { Controller } from '@hotwired/stimulus';
/* stimulusFetch: 'lazy' */
export default class extends Controller {
// ...
}
要使第三方控制器延迟加载,请在 assets/controllers.json
中将 fetch
设置为 lazy
。
注意
如果您使用 TypeScript 编写控制器并且您正在使用 StimulusBundle ≤ 2.21.0,请确保在您的 TypeScript 配置中 removeComments
未设置为 true
。
世界各地的 Stimulus 工具
因为 Stimulus 被 Symfony 以外的开发人员使用,所以除了 UX 包之外还存在许多工具
- stimulus-use:为您的 Stimulus 控制器添加可组合的行为,例如防抖动、检测外部点击以及许多其他功能。
- stimulus-components:大量预制的 Stimulus 控制器,例如用于复制到剪贴板、排序、弹出框(类似于工具提示)等等。
Stimulus Twig 助手
此扩展包添加了一些 Twig 函数/过滤器,以帮助在您的模板中添加 Stimulus 控制器、操作和目标。
注意
尽管此扩展包提供了这些有用的 Twig 函数/过滤器,但建议使用原始数据属性,因为它们更直接。
提示
如果您使用 PhpStorm IDE - 您可能需要安装 Stimulus 插件以获得属性的良好自动完成功能。
stimulus_controller
此扩展包附带一个特殊的 stimulus_controller()
Twig 函数,可用于渲染 Stimulus 控制器和值以及 CSS 类。Stimulus 控制器还可以通过使用 Outlets 引用其他控制器。
例如
1 2 3 4 5 6 7 8 9 10 11 12
<div {{ stimulus_controller('chart', { 'name': 'Likes', 'data': [1, 2, 3, 4] }) }}>
Hello
</div>
<!-- would render -->
<div
data-controller="chart"
data-chart-name-value="Likes"
data-chart-data-value="[1,2,3,4]"
>
Hello
</div>
如果您想设置 CSS 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
<div {{ stimulus_controller('chart', { 'name': 'Likes', 'data': [1, 2, 3, 4] }, { 'loading': 'spinner' }) }}>
Hello
</div>
<!-- would render -->
<div
data-controller="chart"
data-chart-name-value="Likes"
data-chart-data-value="[1,2,3,4]"
data-chart-loading-class="spinner"
>
Hello
</div>
<!-- or without values -->
<div {{ stimulus_controller('chart', controllerClasses = { 'loading': 'spinner' }) }}>
Hello
</div>
以及使用 outlets
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
<div {{ stimulus_controller('chart', { 'name': 'Likes', 'data': [1, 2, 3, 4] }, { 'loading': 'spinner' }, { 'other': '.target' ) }}>
Hello
</div>
<!-- would render -->
<div
data-controller="chart"
data-chart-name-value="Likes"
data-chart-data-value="[1,2,3,4]"
data-chart-loading-class="spinner"
data-chart-other-outlet=".target"
>
Hello
</div>
<!-- or without values/classes -->
<div {{ stimulus_controller('chart', controllerOutlets = { 'other': '.target' }) }}>
Hello
</div>
任何非标量值(例如 data: [1, 2, 3, 4]
)都经过 JSON 编码。并且所有值都已正确转义(字符串 [
是转义的 [
字符,因此属性实际上是 [1,2,3,4]
)。
如果您在同一个元素上有多个控制器,您可以将它们链接起来,因为还有一个 stimulus_controller
过滤器
1 2 3 4 5 6 7 8
<div {{ stimulus_controller('chart', { 'name': 'Likes' })|stimulus_controller('other-controller') }}>
Hello
</div>
<!-- would render -->
<div data-controller="chart other-controller" data-chart-name-value="Likes">
Hello
</div>
您还可以将生成的属性作为数组检索,这对于表单等情况可能很有用
1
{{ form_start(form, { attr: stimulus_controller('chart', { 'name': 'Likes' }).toArray() }) }}
stimulus_action
stimulus_action()
Twig 函数可用于渲染 Stimulus 操作。
例如
1 2 3 4 5 6
<div {{ stimulus_action('controller', 'method') }}>Hello</div>
<div {{ stimulus_action('controller', 'method', 'click') }}>Hello</div>
<!-- would render -->
<div data-action="controller#method">Hello</div>
<div data-action="click->controller#method">Hello</div>
如果您在同一个元素上有多个操作和/或方法,您可以将它们链接起来,因为还有一个 stimulus_action
过滤器
1 2 3 4 5 6 7 8
<div {{ stimulus_action('controller', 'method')|stimulus_action('other-controller', 'test') }}>
Hello
</div>
<!-- would render -->
<div data-action="controller#method other-controller#test">
Hello
</div>
您还可以将生成的属性作为数组检索,这对于表单等情况可能很有用
1
{{ form_row(form.password, { attr: stimulus_action('hello-controller', 'checkPasswordStrength').toArray() }) }}
您还可以将参数传递给操作
1 2 3 4
<div {{ stimulus_action('hello-controller', 'method', 'click', { 'count': 3 }) }}>Hello</div>
<!-- would render -->
<div data-action="click->hello-controller#method" data-hello-controller-count-param="3">Hello</div>
stimulus_target
stimulus_target()
Twig 函数可用于渲染 Stimulus 目标。
例如
1 2 3 4 5 6
<div {{ stimulus_target('controller', 'myTarget') }}>Hello</div>
<div {{ stimulus_target('controller', 'myTarget secondTarget') }}>Hello</div>
<!-- would render -->
<div data-controller-target="myTarget">Hello</div>
<div data-controller-target="myTarget secondTarget">Hello</div>
如果您在同一个元素上有多个目标,您可以将它们链接起来,因为还有一个 stimulus_target
过滤器
1 2 3 4 5 6 7 8
<div {{ stimulus_target('controller', 'myTarget')|stimulus_target('other-controller', 'anotherTarget') }}>
Hello
</div>
<!-- would render -->
<div data-controller-target="myTarget" data-other-controller-target="anotherTarget">
Hello
</div>
您还可以将生成的属性作为数组检索,这对于表单等情况可能很有用
1
{{ form_row(form.password, { attr: stimulus_target('hello-controller', 'myTarget').toArray() }) }}
配置
如果您正在使用 AssetMapper,如果您需要使用不同的路径,则可以配置控制器目录和 controllers.json
文件的路径
1 2 3 4 5 6
# config/packages/stimulus.yaml
stimulus:
# the default values
controller_paths:
- '%kernel.project_dir%/assets/controllers'
controllers_json: '%kernel.project_dir%/assets/controllers.json'
手动安装详情
当您安装此扩展包时,其 Flex 配方应处理更新所有需要的文件。如果您未使用 Flex 或想仔细检查更改,请查看 StimulusBundle Flex 配方。以下是其中内容的摘要
assets/bootstrap.js
启动 Stimulus 应用程序并加载您的控制器。它由assets/app.js
导入,其确切内容取决于您是否安装了 Webpack Encore 或 AssetMapper(见下文)。assets/app.js
已更新为导入assets/bootstrap.js
assets/controllers.json
此文件开始时(大部分)为空,并在您安装提供 Stimulus 控制器的 UX 包时自动更新。assets/controllers/
此目录是您应该放置自定义 Stimulus 控制器的地方。它带有一个示例hello_controller.js
文件。
其他一些更改取决于您使用的资源系统
使用 AssetMapper
如果您正在使用 AssetMapper,则会在您的 importmap.php
文件中添加两个新条目
1 2 3 4 5 6 7 8 9 10 11
// importmap.php
return [
// ...
'@symfony/stimulus-bundle' => [
'path' => '@symfony/stimulus-bundle/loader.js',
],
'@hotwired/stimulus' => [
'version' => '3.2.2',
],
];
配方将更新您的 assets/bootstrap.js
文件,使其看起来像这样
1 2 3 4
// assets/bootstrap.js
import { startStimulusApp } from '@symfony/stimulus-bundle';
const app = startStimulusApp();
@symfony/stimulus-bundle
指的是您的 importmap.php
文件中的新条目之一。此文件由扩展包动态构建,并将导入您的所有自定义控制器以及来自 controllers.json
的控制器。当您的应用程序在调试模式下运行时,它还将在 Stimulus 中动态启用“调试”模式。
提示
仅对于 AssetMapper 6.3,您还需要在 base.html.twig
中使用 {{ ux_controller_link_tags() }}
。AssetMapper 6.4+ 中不需要此项。
使用 WebpackEncoreBundle
如果您正在使用 Webpack Encore,则配方还将更新您的 webpack.config.js
文件以包含此行
1 2
// webpack.config.js
.enableStimulusBridge('./assets/controllers.json')
assets/bootstrap.js
文件将更新为如下所示
1 2 3 4 5 6 7 8 9
// assets/bootstrap.js
import { startStimulusApp } from '@symfony/stimulus-bridge';
// Registers Stimulus controllers from controllers.json and in the controllers/ directory
export const app = startStimulusApp(require.context(
'@symfony/stimulus-bridge/lazy-controller-loader!./controllers',
true,
/\.[jt]sx?$/
));
并且 2 个新软件包 - @hotwired/stimulus
和 @symfony/stimulus-bridge
- 将添加到您的 package.json
文件中。
Stimulus 控制器是如何加载的?
当您安装 UX PHP 包时,Symfony Flex 会自动更新您的 package.json
文件(如果使用 AssetMapper,则不需要这样做)以指向位于该 PHP 包内的“虚拟包”。例如
1 2 3 4 5 6
{
"devDependencies": {
"...": "",
"@symfony/ux-chartjs": "file:vendor/symfony/ux-chartjs/assets"
}
}
这为您提供了一个真正的 Node 包(例如 @symfony/ux-chartjs
),它不是被下载,而是直接指向已存在于您的 vendor/
目录中的文件。
Flex 配方通常还会更新您的 assets/controllers.json
文件,以向您的应用程序添加新的 Stimulus 控制器。例如
1 2 3 4 5 6 7 8 9 10 11
{
"controllers": {
"@symfony/ux-chartjs": {
"chart": {
"enabled": true,
"fetch": "eager"
}
}
},
"entrypoints": []
}
最后,您的 assets/bootstrap.js
文件将自动注册
assets/controllers/
中的所有文件作为 Stimulus 控制器;- 以及
assets/controllers.json
中描述的所有控制器作为 Stimulus 控制器。
注意
如果您正在使用 WebpackEncore,则 bootstrap.js
文件与 @symfony/stimulus-bridge 协同工作。对于 AssetMapper,bootstrap.js
文件直接与此扩展包一起工作:通过 Flex 将 @symfony/stimulus-bundle
条目添加到您的 importmap.php
文件中,该条目指向一个动态构建的文件,用于查找和加载您的控制器(请参阅配置)。
最终结果:您安装一个包,并且立即拥有可用的 Stimulus 控制器!在本例中,它被称为 @symfony/ux-chartjs/chart
。好吧,从技术上讲,它将被称为 symfony--ux-chartjs--chart
。但是,您可以将原始名称传递到 WebpackEncoreBundle 中的 {{ stimulus_controller() }}
函数,它会将其规范化
1 2 3 4
<div {{ stimulus_controller('@symfony/ux-chartjs/chart') }}>
<!-- will render as: -->
<div data-controller="symfony--ux-chartjs--chart">