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.4k
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
13
8.8k
どうしてこうなった?から理解するActive Recordの関連の裏側
willnet
5
940
Exceptional Rails
willnet
6
6.9k
Breaking the Flaky Test Cycle
willnet
2
2k
mrskで広がるインフラの選択肢
willnet
1
980
アプリケーションを長期にわたって無理なく運用するためのたったひとつの方法
willnet
2
2.1k
HotwireからDHHが考えるこれからのRailsとJSの付き合い方を知る
willnet
14
13k
Rails6.1で新しく入る機能について
willnet
12
15k
Concerns about Concerns
willnet
11
34k
Other Decks in Technology
See All in Technology
TanStack Routerに移行するのかい しないのかい、どっちなんだい! / Are you going to migrate to TanStack Router or not? Which one is it?
kaminashi
0
590
Terraform未経験の御様に対してどの ように導⼊を進めていったか
tkikuchi
2
430
TypeScript、上達の瞬間
sadnessojisan
46
13k
組織成長を加速させるオンボーディングの取り組み
sudoakiy
2
150
インフラとバックエンドとフロントエンドをくまなく調べて遅いアプリを早くした件
tubone24
1
430
AWS Lambdaと歩んだ“サーバーレス”と今後 #lambda_10years
yoshidashingo
1
170
Shopifyアプリ開発における Shopifyの機能活用
sonatard
4
250
これまでの計測・開発・デプロイ方法全部見せます! / Findy ISUCON 2024-11-14
tohutohu
3
370
OCI Security サービス 概要
oracle4engineer
PRO
0
6.5k
初心者向けAWS Securityの勉強会mini Security-JAWSを9ヶ月ぐらい実施してきての近況
cmusudakeisuke
0
120
誰も全体を知らない ~ ロールの垣根を超えて引き上げる開発生産性 / Boosting Development Productivity Across Roles
kakehashi
1
230
SRE×AIOpsを始めよう!GuardDutyによるお手軽脅威検出
amixedcolor
0
110
Featured
See All Featured
Writing Fast Ruby
sferik
627
61k
Teambox: Starting and Learning
jrom
133
8.8k
The Power of CSS Pseudo Elements
geoffreycrofte
73
5.3k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
280
13k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
26
2.1k
The Art of Programming - Codeland 2020
erikaheidi
52
13k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
226
22k
Happy Clients
brianwarren
98
6.7k
We Have a Design System, Now What?
morganepeng
50
7.2k
A Philosophy of Restraint
colly
203
16k
Agile that works and the tools we love
rasmusluckow
327
21k
No one is an island. Learnings from fostering a developers community.
thoeni
19
3k
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でやればいいんだよ
以上