この記事はGoogle翻訳の結果を編集したものです。
前の章では値を使用してコントローラーの内部状態をロードして永続化する方法を学びました。
コントローラーは外部リソースの状態を追跡する必要がある場合があります。外部とはDOMまたはStimulusの一部にないものを意味します。たとえばHTTPリクエストを発行し、リクエストの状態が変化したときに応答する必要がある場合があります。またはタイマーを開始してコントローラーが接続されなくなったときに停止することもできます。この章ではこれらの両方を行う方法を見ていきます。
HTMLの非同期読み込み
HTMLのリモートフラグメントを読み込んで挿入することにより、ページの一部を非同期的に設定する方法を学びましょう。Basecampでこの手法を使用して最初のページの読み込みを高速に保ち、ビューをユーザー固有のコンテンツから解放してより効果的にキャッシュできるようにします。
サーバーから取得したHTMLを要素に取り込む汎用コンテンツローダーコントローラーを作成します。 次に、これを使用してメールの受信トレイに表示されるような未読メッセージのリストを読み込みます。
public/index.html
で受信トレイをスケッチすることから始めます。
<div data-controller="content-loader"
data-content-loader-url-value="/messages.html"></div>
次にメッセージリスト用のHTMLを含む新しいpublic/messages.html
ファイルを作成します。
<ol>
<li>New Message: Stimulus Launch Party</li>
<li>Overdue: Finish Stimulus 1.0</li>
</ol>
(実際のアプリケーションではこのHTMLをサーバー上で動的に生成しますが、デモ用に静的ファイルを使用します。)
これでコントローラーを実装できます。
// src/controllers/content_loader_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static values = { url: String }
connect() {
this.load()
}
load() {
fetch(this.urlValue)
.then(response => response.text())
.then(html => this.element.innerHTML = html)
}
}
コントローラーが接続すると要素のdata-content-loader-url-value
属性で指定されたURLへのFetchリクエストを開始します。次に返されたHTMLを要素のinnerHTML
プロパティに割り当てて読み込みます。
ブラウザーの開発者コンソールでネットワーク タブを開き、ページをリロードします。最初のページの読み込みを表すリクエストが表示され、その後にコントローラーのmessages.html
へのリクエストが続きます。
タイマーで自動リフレッシュ
受信トレイを定期的に更新して常に最新の状態に保つように変更して、コントローラーを改善しましょう。
data-content-loader-refresh-interval-value
属性を使用してコントローラーがコンテンツをリロードする頻度をミリ秒単位で指定します。
<div data-controller="content-loader"
data-content-loader-url-value="/messages.html"
data-content-loader-refresh-interval-value="5000"></div>
これでコントローラーを更新して間隔を確認し、存在する場合は更新タイマーを開始できます。
コントローラーに静的値の定義を追加し、新しいメソッドstartRefreshing()
を定義します。
export default class extends Controller {
static values = { url: String, refreshInterval: Number }
startRefreshing() {
setInterval(() => {
this.load()
}, this.refreshIntervalValue)
}
// …
}
次にインターバル値が存在する場合にstartRefreshing()
を呼び出すようにconnect()
メソッドを更新します。
connect() {
this.load()
if (this.hasRefreshIntervalValue) {
this.startRefreshing()
}
}
ページをリロードし、開発者コンソールで5秒ごとに新しいリクエストを観察します。次にpublic/messages.html
変更を加えて受信トレイに表示されるまで待ちます。
追跡されたリソースを解放する
コントローラーが接続されたときにタイマーを開始しますが、停止することはありません。つまり、コントローラーの要素が消えてもコントローラーはバックグラウンドでHTTPリクエストを発行し続けることになります。
この問題はタイマーへの参照を保持するようにstartRefreshing()
メソッドを変更することで修正できます。
startRefreshing() {
this.refreshTimer = setInterval(() => {
this.load()
}, this.refreshIntervalValue)
}
次に、対応するstopRefreshing()
メソッドを以下に追加してタイマーをキャンセルできます。
stopRefreshing() {
if (this.refreshTimer) {
clearInterval(this.refreshTimer)
}
}
最後に、コントローラーが切断されたときにタイマーをキャンセルするようにStimulusに指示するためにdisconnect()
メソッドを追加します。
disconnect() {
this.stopRefreshing()
}
これでコンテンツローダーコントローラーがDOMに接続されている場合にのみリクエストを発行することを確認できます。
最終的なコントローラークラスを見てみましょう。
// src/controllers/content_loader_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static values = { url: String, refreshInterval: Number }
connect() {
this.load()
if (this.hasRefreshIntervalValue) {
this.startRefreshing()
}
}
disconnect() {
this.stopRefreshing()
}
load() {
fetch(this.urlValue)
.then(response => response.text())
.then(html => this.element.innerHTML = html)
}
startRefreshing() {
this.refreshTimer = setInterval(() => {
this.load()
}, this.refreshIntervalValue)
}
stopRefreshing() {
if (this.refreshTimer) {
clearInterval(this.refreshTimer)
}
}
}
アクションパラメーターの使用
ローダーを複数の異なるソースで動作させたい場合、アクションパラメーターを使用して実行できます。 次のHTMLを使用します。
<div data-controller="content-loader">
<a href="#" data-content-loader-url-param="/messages.html" data-action="content-loader#load">Messages</a>
<a href="#" data-content-loader-url-param="/comments.html" data-action="content-loader#load">Comments</a>
</div>
次にload
アクションを介してこれらのパラメーターを使用できます。
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
load({ params }) {
fetch(params.url)
.then(response => response.text())
.then(html => this.element.innerHTML = html)
}
}
パラメーターを破棄して、URLパラメータを取得することもできます。
load({ params: { url } }) {
fetch(url)
.then(response => response.text())
.then(html => this.element.innerHTML = html)
}
まとめと次のステップ
この章ではStimulusライフサイクルコールバックを使用して外部リソースを取得および解放する方法を見てきました。
次に独自のアプリケーションにStimulusをインストールして構成する方法を見ていきます。