Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
stimulus
Search
Shinichi Maeshima
October 16, 2018
Technology
0
4.6k
stimulus
ginza.rb#64 でstimulusを紹介したときに使った資料です
https://ginzarb.doorkeeper.jp/events/81390
Shinichi Maeshima
October 16, 2018
Tweet
Share
More Decks by Shinichi Maeshima
See All by Shinichi Maeshima
Sidekiq vs Solid Queue
willnet
14
12k
どうしてこうなった?から理解するActive Recordの関連の裏側
willnet
6
1.4k
Exceptional Rails
willnet
6
7.5k
Breaking the Flaky Test Cycle
willnet
2
2.1k
mrskで広がるインフラの選択肢
willnet
1
1.1k
アプリケーションを長期にわたって無理なく運用するためのたったひとつの方法
willnet
2
2.2k
HotwireからDHHが考えるこれからのRailsとJSの付き合い方を知る
willnet
14
13k
Rails6.1で新しく入る機能について
willnet
12
16k
Concerns about Concerns
willnet
11
34k
Other Decks in Technology
See All in Technology
Model Mondays S2E03: SLMs & Reasoning
nitya
0
210
生成AI時代 文字コードを学ぶ意義を見出せるか?
hrsued
1
660
ドメイン特化なCLIPモデルとデータセットの紹介
tattaka
1
220
TechLION vol.41~MySQLユーザ会のほうから来ました / techlion41_mysql
sakaik
0
190
Oracle Audit Vault and Database Firewall 20 概要
oracle4engineer
PRO
3
1.7k
AWS Summit Japan 2025 Community Stage - App workflow automation by AWS Step Functions
matsuihidetoshi
1
300
Lambda Web Adapterについて自分なりに理解してみた
smt7174
5
130
asken AI勉強会(Android)
tadashi_sato
0
110
論文紹介:LLMDet (CVPR2025 Highlight)
tattaka
0
110
AIの最新技術&テーマをつまんで紹介&フリートークするシリーズ #1 量子機械学習の入門
tkhresk
0
140
Tech-Verse 2025 Keynote
lycorptech_jp
PRO
0
970
CursorによるPMO業務の代替 / Automating PMO Tasks with Cursor
motoyoshi_kakaku
1
500
Featured
See All Featured
Large-scale JavaScript Application Architecture
addyosmani
512
110k
Building Adaptive Systems
keathley
43
2.6k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.4k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Done Done
chrislema
184
16k
VelocityConf: Rendering Performance Case Studies
addyosmani
331
24k
A designer walks into a library…
pauljervisheath
207
24k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
3.9k
Designing for Performance
lara
609
69k
Building Flexible Design Systems
yeseniaperezcruz
328
39k
Embracing the Ebb and Flow
colly
86
4.7k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
46
9.6k
Transcript
stimulus — ginza.rb#64 — @willnet
とは — Stimulus: A modest JavaScript framework for the HTML
you already have. — Basecamp製のJSフレームワーク — 現在のバージョン1.1.0(2018/8/23)
試用 — webpackなどでプリコンパイルするのを推奨 — cloneしてサッと試せるお試し用リポジトリがある — stimulusjs/stimulus-starter: A humble blank
slate for a modest JavaScript framework — rails使いなら rails new --webpack=stimulus yourappname でも環境作れるのでそっちでもよさそう — 公式チュートリアル的なのがあるので、それを見ながら手 を動かすとよいのでは
特徴 — react や vue.js とは志向がぜんぜん違う — データバインディングとかVirtual DOMとか、なにそれ 美味しいの?って感じ
— あくまでサーバが吐くHTMLと仲良くするためのフレーム ワーク — turbolinks friendly — サーバサイドの人が片手間でやるフロントエンドで、 vue.jsなどを導入する余裕がない…みたいなときに導入す るのが良いのでは、という気がする — 現行のjsを整理するために使う
どういうときに便利そうか — 通常RailsのJSはファイルごとにそれっぽく関数やイベント 登録などが整理されるけれど、特に強制力はない — なのでフラットにイベントが登録されたり、関数が登録 されたりする可能性がある — 例えば users.js
に user とあまり関係ない関数が 登録されたりする — DOMのclass属性とjsが紐付けられる事が多いけど、cssのた めに使うclassなのかjsで使うclassなのか分かりづらい — stimulusを使うとDOMに controller, target, action を割 り振ることができ、規約によって関数群を整理できる、と いうのがstimulusのキモの一つ(だと思う)
どういうときに便利そうか — turbolinksを使っているときに、特定のページでだけ実行 したい処理を書くのが面倒 — 特定のDOMがあるかチェックして、なかったらreturnす る、みたいな処理を毎回書く — だるい
こういうやつ $(document).on('ready turbolinks:load', () => { const target = $('.condition_transfer_on')
if (target.length === 0) { return } // .condition_transfer_on͕͋ͬͨ߹ͷॲཧ — stimulusを使うと「controllerがページ表示されたタイミ ング(connectされたタイミング)でなにか処理を実行する」 みたいなのが楽にかける
controller, target, action とは stimulus 公式のトップページを見ながら解説するとわかりや すそう Stimulus: A modest
JavaScript framework for the HTML you already have.
HTMLのコード <div data-controller="hello"> <input data-target="hello.name" type="text"> <button data-action="click->hello#greet"> Greet </button>
<span data-target="hello.output"> </span> </div>
jsのコード import { Controller } from "stimulus" export default class
extends Controller { static targets = [ "name", "output" ] greet() { this.outputTarget.textContent = `Hello, ${this.nameTarget.value}!` } }
結果 名前を入力してGreet!をクリックすると、右側に名前を含んだ 文字列が出力される
HTMLとjsの対応付け — data-controllerの値とjsファイル名が紐付いている — data-actionの値とメソッドが紐付いている — data-targetの値とstatic targets = []
で定義された値が 紐付いている — static targets = ["name"] などとすると、 this.nameTarget でDOMの要素を扱うことができるよう になる
stimulusの大まかな機能は これだけ
完?
それぞれもうちょっと詳し く
controller — html中のdata-controllerに合わせて、紐付いた名前の controllerをインスタンス化し、DOMと紐づけてくれる — 例えば<div data-controller="hello"> であれば hello-controller.jsが自動的に読み込まれる —
ファイル名にアンダースコアを使うこともできる — date_picker_controller.js -> date-picker — 参考: https://stimulusjs.org/handbook/ installing#controller-filenames-map-to- identifiers
複数のコントローラを一つのDOMに紐付けること ができる <div data-controller="clipboard list-item"></div>
コントローラを複数のDOMに紐付けることができ る <ul> <li data-controller="list-item">One</li> <li data-controller="list-item">Two</li> <li data-controller="list-item">Three</li> </ul>
li要素それぞれに、別々のコントローラのインスタンスが割り 当てられる
action <div data-controller="gallery"> <button data-action="click->gallery#next">…</button> </div> — イベントの名前(click) — コントローラ名(garraly)
— アクション名(next) をそれぞれ指定する
eventオブジェクト actionとして定義されたメソッドに、eventオブジェクトが引 数として渡ってくる import { Controller } from "stimulus" export
default class extends Controller { next(event) { // … } }
eventオブジェクト — event.type でなんのイベントなのかが返る(例: 'click') — event.targetでどのDOM発祥なのか返る — event.currentTargetでイベントリスナが登録されている DOMが返る
イベントの名前 — DOM要素によっては省略できる — 例えばa要素ならclickがデフォルトで省略可能
同じDOMに複数イベント登録できる <input type="text" data-action="focus->field#highlight input->search#update">
target Action以外のDOMとjsの紐づけはtargetでやる
html <div data-controller="search"> <input type="text" data-target="search.query"> <div data-target="search.errorMessage"></div> <div data-target="search.results"></div>
</div> controller໊.target໊ で指定する
js import { Controller } from "stimulus" export default class
extends Controller { static targets = [ "query", "errorMessage", "results" ] // … } — statis targets に配列でtargetになる要素の名前を渡す — すると後述のプロパティが生える
プロパティ 例えばqueryという名前のtargetを指定すると次のプロパティ が自動で生える — this.queryTarget — 最初にマッチしたDOMが返る — this.queriesTarget —
マッチしたDOMが全部返る — this.hasQueryTarget — DOMが存在しているのかbooleanで返る
一つのDOMに複数のtargetを指定できる <form data-controller="search checkbox"> <input type="checkbox" data-target="search.projects checkbox.input"> <input type="checkbox"
data-target="search.messages checkbox.input"> … </form>
Data Maps <div data-controller="content-loader" data-content-loader-url="/messages"> </div> — 状態をどこで持つのか、という話 — 他のjsフレームワークはjsで持つけど、stimulusjsはDOMで
持つ — html側からjs(その逆も)になにかデータを渡すとき、data- ίϯτϩʔϥ໊-σʔλ໊で渡すというのがstimulusjsでの お作法
js // controllers/content_loader_controller.js import { Controller } from "stimulus" export
default class extends Controller { connect() { fetch(this.data.get("url")).then(/* … */) } } — this.data.get("url")でdata-content-loader-urlの値を取 得できる
その他のメソッド — this.data.set(key, value) — DOMの方にデータを設定する — this.data.has(key) — booleanで、そのkeyのdataが存在しているのか返す
— this.data.delete(key) — keyに紐づくdataを消す
注意点 — dataはNumberでアサインしても、getするとStringで返って くる — とくに型変換とかはしてないもよう this.data.set("count", 1) this.data.get("count") //
"1"
Lifecycle Callback controllerのインスタンスがDOMに割り当てられたときなどに hookしてメソッド実行をさせることができる import { Controller } from "stimulus"
export default class extends Controller { connect() { // … } }
メソッド — initialize — controllerのインスタンスが作られたタイミング — connect — DOMに紐付いたタイミング —
ドキュメント上にdata-controllerを持つDOMが現れたら connectされる — disconnect — DOMとの紐づけがなくなったタイミング — data-controllerを持つDOMが消されたり、data- controller属性自体が消されたりしたらdisconnect
DOMが存在する/しないで自動でcontrollerが紐付けられるというのが — turbolinksフレンドリーってことっぽい?
インスタンスは使い回される — disconnectしたあとにまたconnectされるケースでは、イン スタンスが使い回される — つまりconnectやdisconnectは複数回呼ばれる可能性が ある
まとめ
メリット — 学習コストがめっちゃ低い — 一日あれば使えるようになるのでは? — vannilajsやjQueryで作っているサービスから移行しやすい — 試してみた結果やめたくなった場合も比較的やめやすそう
デメリット — vannilajsから移行しても「単にメソッドやイベントを整理 した」以上にはならない — マジカルな何かですごいことになる、ということはない — できることが限定的 — SPAとか無理(そういうのはturbolinks使って擬似的にや
ればいいじゃん、という考え) — JSON APIを叩いて云々、とかは考えてない — クライアントサイドでDOMを組み立てる、なんて大変で しょ?全部HTMLでやればいいんだよ
以上