跳到主要內容

StimulusBundle:Symfony 與 Stimulus 的整合

編輯此頁面

提示

https://ux.symfony.com 查看 Symfony UX 的即時示範!

此套件增加了 Symfony、Stimulus 和 Symfony UX 套件之間的整合

  • Twig stimulus_ 函式與過濾器,用於新增 Stimulus 控制器、
    在您的模板中新增動作與目標;
  • 整合載入 UX 套件(額外的 Stimulus 控制器)

安裝

首先,如果您還沒有資產處理系統,請選擇並安裝一個;兩者都與 StimulusBundle 完美搭配

請參閱 Encore 與 AssetMapper 的比較,以了解哪一個最適合您的專案。

下一步,安裝此套件

1
$ composer require symfony/stimulus-bundle

如果您使用 Symfony Flex,就完成了!Recipe 將會更新必要的檔案。如果沒有使用 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 套件包括

延遲載入 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="&#x5B;1,2,3,4&#x5D;"
>
   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="&#x5B;1,2,3,4&#x5D;"
   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="&#x5B;1,2,3,4&#x5D;"
   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 編碼。並且所有值都會被正確逸出(字串 &#x5B; 是一個逸出的 [ 字元,因此屬性實際上是 [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 recipe 應該會處理更新所有需要的檔案。如果您未使用 Flex 或想要再次檢查變更,請查看 StimulusBundle Flex recipe。以下是其中內容的摘要

  • 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',
    ],
];

Recipe 將會更新您的 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 中的「debug」模式。

提示

僅針對 AssetMapper 6.3,您還需要在 base.html.twig 中加入 {{ ux_controller_link_tags() }}。AssetMapper 6.4+ 中則不需要。

使用 WebpackEncoreBundle

如果您使用 Webpack Encore,recipe 也會更新您的 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 檔案會直接與此套件組搭配運作:@symfony/stimulus-bundle 條目會透過 Flex 新增至您的 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">
這項工作,包括程式碼範例,已根據 Creative Commons BY-SA 3.0 授權條款授權。
目錄
    版本