Halogen,Thermite,Riotの紹介 / Introduction to Halogen, Thermite and Riot

5f533aeab28ed4f70c26e336e71296f7?s=47 tipo159
August 29, 2017

Halogen,Thermite,Riotの紹介 / Introduction to Halogen, Thermite and Riot

Halogen,Thermite,Riotの簡単な紹介とTodoMVCのコード量の比較

5f533aeab28ed4f70c26e336e71296f7?s=128

tipo159

August 29, 2017
Tweet

Transcript

  1. Halogen, Thermite, Riotの紹介 Halogen, Thermite, Riotの紹介 Halogen, Thermite, Riotの紹介 Halogen,

    Thermite, Riotの紹介 Halogen, Thermite, Riotの紹介 Halogen, Thermite, Riotの紹介 by tipo159 by tipo159 by tipo159 by tipo159 by tipo159 by tipo159 2017-08-29 2017-08-29 2017-08-29 2017-08-29 2017-08-29 2017-08-29 1 / 47
  2. Halogenの概要 Halogenの概要 Halogenの概要 Halogenの概要 Halogenの概要 Halogenの概要 宣言型,型安全なPureScript UIライブラリ 宣言型,型安全なPureScript UIライブラリ

    宣言型,型安全なPureScript UIライブラリ 宣言型,型安全なPureScript UIライブラリ 宣言型,型安全なPureScript UIライブラリ 宣言型,型安全なPureScript UIライブラリ Virtual-DOMを使用 Virtual-DOMを使用 Virtual-DOMを使用 Virtual-DOMを使用 Virtual-DOMを使用 Virtual-DOMを使用 Halogenアプリケーションをコンポーネントのツリーとして構成 Halogenアプリケーションをコンポーネントのツリーとして構成 Halogenアプリケーションをコンポーネントのツリーとして構成 Halogenアプリケーションをコンポーネントのツリーとして構成 Halogenアプリケーションをコンポーネントのツリーとして構成 Halogenアプリケーションをコンポーネントのツリーとして構成 各コンポーネントは,独自の状態と状態変更時のレンダラを持つ 各コンポーネントは,独自の状態と状態変更時のレンダラを持つ 各コンポーネントは,独自の状態と状態変更時のレンダラを持つ 各コンポーネントは,独自の状態と状態変更時のレンダラを持つ 各コンポーネントは,独自の状態と状態変更時のレンダラを持つ 各コンポーネントは,独自の状態と状態変更時のレンダラを持つ 自己完結ユニット 自己完結ユニット 自己完結ユニット 自己完結ユニット 自己完結ユニット 自己完結ユニット                        
  3. 状態の更新 状態の更新 状態の更新 状態の更新 状態の更新 状態の更新 コンポーネントは, コンポーネントは, コンポーネントは, コンポーネントは,

    コンポーネントは, コンポーネントは,クエリ クエリ クエリ クエリ クエリ クエリ (入力)を評価することで自身の状態を (入力)を評価することで自身の状態を (入力)を評価することで自身の状態を (入力)を評価することで自身の状態を (入力)を評価することで自身の状態を (入力)を評価することで自身の状態を 更新 更新 更新 更新 更新 更新 各コンポーネントは,取り得るすべてのクエリの型を定義 各コンポーネントは,取り得るすべてのクエリの型を定義 各コンポーネントは,取り得るすべてのクエリの型を定義 各コンポーネントは,取り得るすべてのクエリの型を定義 各コンポーネントは,取り得るすべてのクエリの型を定義 各コンポーネントは,取り得るすべてのクエリの型を定義 入力ではなくクエリと呼ぶのは,状態を更新するだけでなくコン 入力ではなくクエリと呼ぶのは,状態を更新するだけでなくコン 入力ではなくクエリと呼ぶのは,状態を更新するだけでなくコン 入力ではなくクエリと呼ぶのは,状態を更新するだけでなくコン 入力ではなくクエリと呼ぶのは,状態を更新するだけでなくコン 入力ではなくクエリと呼ぶのは,状態を更新するだけでなくコン ポーネントの状態の詳細を返却できるため ポーネントの状態の詳細を返却できるため ポーネントの状態の詳細を返却できるため ポーネントの状態の詳細を返却できるため ポーネントの状態の詳細を返却できるため ポーネントの状態の詳細を返却できるため                  
  4. メッセージ メッセージ メッセージ メッセージ メッセージ メッセージ コンポーネントは,クエリの評価中にメッセージを送出可能 コンポーネントは,クエリの評価中にメッセージを送出可能 コンポーネントは,クエリの評価中にメッセージを送出可能 コンポーネントは,クエリの評価中にメッセージを送出可能

    コンポーネントは,クエリの評価中にメッセージを送出可能 コンポーネントは,クエリの評価中にメッセージを送出可能 クエリと同様に,コンポーネント毎にメッセージの型を定義 クエリと同様に,コンポーネント毎にメッセージの型を定義 クエリと同様に,コンポーネント毎にメッセージの型を定義 クエリと同様に,コンポーネント毎にメッセージの型を定義 クエリと同様に,コンポーネント毎にメッセージの型を定義 クエリと同様に,コンポーネント毎にメッセージの型を定義 メッセージで,コンポーネントのアクティビティをリスナーに通 メッセージで,コンポーネントのアクティビティをリスナーに通 メッセージで,コンポーネントのアクティビティをリスナーに通 メッセージで,コンポーネントのアクティビティをリスナーに通 メッセージで,コンポーネントのアクティビティをリスナーに通 メッセージで,コンポーネントのアクティビティをリスナーに通 知 知 知 知 知 知 例えば,親コンポーネントが子コンポーネントのアクティビティ 例えば,親コンポーネントが子コンポーネントのアクティビティ 例えば,親コンポーネントが子コンポーネントのアクティビティ 例えば,親コンポーネントが子コンポーネントのアクティビティ 例えば,親コンポーネントが子コンポーネントのアクティビティ 例えば,親コンポーネントが子コンポーネントのアクティビティ を観測するために使用 を観測するために使用 を観測するために使用 を観測するために使用 を観測するために使用 を観測するために使用                        
  5. 純粋 純粋 純粋 純粋 純粋 純粋 (関数型) (関数型) (関数型) (関数型)

    (関数型) (関数型) コンポーネント定義は純粋(関数型) コンポーネント定義は純粋(関数型) コンポーネント定義は純粋(関数型) コンポーネント定義は純粋(関数型) コンポーネント定義は純粋(関数型) コンポーネント定義は純粋(関数型) rootコンポーネントを動作させることでUIを生成 rootコンポーネントを動作させることでUIを生成 rootコンポーネントを動作させることでUIを生成 rootコンポーネントを動作させることでUIを生成 rootコンポーネントを動作させることでUIを生成 rootコンポーネントを動作させることでUIを生成 非同期なUIを実現するために,PureScriptのA を使用 非同期なUIを実現するために,PureScriptのA を使用 非同期なUIを実現するために,PureScriptのA を使用 非同期なUIを実現するために,PureScriptのA を使用 非同期なUIを実現するために,PureScriptのA を使用 非同期なUIを実現するために,PureScriptのA を使用                  
  6. コンポーネントの状態 コンポーネントの状態 コンポーネントの状態 コンポーネントの状態 コンポーネントの状態 コンポーネントの状態 TodoではTaskとListを使用 TodoではTaskとListを使用 TodoではTaskとListを使用 TodoではTaskとListを使用

    TodoではTaskとListを使用 TodoではTaskとListを使用 type type TaskId TaskId = = Int Int type type Task Task = = { { description description :: :: String String , , completed completed :: :: Boolean Boolean } } type type List List = = { { tasks tasks :: :: Array Array TaskId TaskId , , nextId nextId :: :: TaskId TaskId , , numCompleted numCompleted :: :: Int Int } }      
  7. クエリ代数 クエリ代数 クエリ代数 クエリ代数 クエリ代数 クエリ代数 コンポーネント毎のクエリの型定義は,クエリ代数と呼ばれる コンポーネント毎のクエリの型定義は,クエリ代数と呼ばれる コンポーネント毎のクエリの型定義は,クエリ代数と呼ばれる コンポーネント毎のクエリの型定義は,クエリ代数と呼ばれる

    コンポーネント毎のクエリの型定義は,クエリ代数と呼ばれる コンポーネント毎のクエリの型定義は,クエリ代数と呼ばれる クエリ代数は,型 -> 型のように定義される クエリ代数は,型 -> 型のように定義される クエリ代数は,型 -> 型のように定義される クエリ代数は,型 -> 型のように定義される クエリ代数は,型 -> 型のように定義される クエリ代数は,型 -> 型のように定義される data data TaskQuery TaskQuery a a = = UpdateDescription UpdateDescription String String a a | | ToggleCompleted ToggleCompleted Boolean Boolean a a | | Remove Remove a a | | IsCompleted IsCompleted ( (Boolean Boolean -> -> a a) )            
  8. 入力値 入力値 入力値 入力値 入力値 入力値 親コンポーネントから子コンポーネントに値を渡すために入力値 親コンポーネントから子コンポーネントに値を渡すために入力値 親コンポーネントから子コンポーネントに値を渡すために入力値 親コンポーネントから子コンポーネントに値を渡すために入力値

    親コンポーネントから子コンポーネントに値を渡すために入力値 親コンポーネントから子コンポーネントに値を渡すために入力値 を使用 を使用 を使用 を使用 を使用 を使用 例えば,UpdateDescriptionの入力値はタスクの詳細 例えば,UpdateDescriptionの入力値はタスクの詳細 例えば,UpdateDescriptionの入力値はタスクの詳細 例えば,UpdateDescriptionの入力値はタスクの詳細 例えば,UpdateDescriptionの入力値はタスクの詳細 例えば,UpdateDescriptionの入力値はタスクの詳細            
  9. 出力メッセージ 出力メッセージ 出力メッセージ 出力メッセージ 出力メッセージ 出力メッセージ 出力メッセージの型も定義 出力メッセージの型も定義 出力メッセージの型も定義 出力メッセージの型も定義

    出力メッセージの型も定義 出力メッセージの型も定義 data data TaskMessage TaskMessage = = NotifyRemove NotifyRemove | | Toggled Toggled Boolean Boolean      
  10. レンダリング レンダリング レンダリング レンダリング レンダリング レンダリング コンポーネントがどのように表示されるかを宣言 コンポーネントがどのように表示されるかを宣言 コンポーネントがどのように表示されるかを宣言 コンポーネントがどのように表示されるかを宣言

    コンポーネントがどのように表示されるかを宣言 コンポーネントがどのように表示されるかを宣言 レンダ関数は,コンポーネントが生成された時と変更された時に レンダ関数は,コンポーネントが生成された時と変更された時に レンダ関数は,コンポーネントが生成された時と変更された時に レンダ関数は,コンポーネントが生成された時と変更された時に レンダ関数は,コンポーネントが生成された時と変更された時に レンダ関数は,コンポーネントが生成された時と変更された時に 呼ばれる 呼ばれる 呼ばれる 呼ばれる 呼ばれる 呼ばれる render render :: :: Task Task -> -> H.ComponentHTML H.ComponentHTML TaskQuery TaskQuery render render t t = = bimap bimap id id id id $ $ HH.li_ HH.li_ [ [ HH.input HH.input [ [ HP.type_ HP.type_ HP.InputCheckbox HP.InputCheckbox , , HP.title HP.title "Mark as completed" "Mark as completed" , , HP.checked HP.checked t t. .completed completed , , HE.onChecked HE.onChecked ( (HE.input HE.input ToggleCompleted ToggleCompleted) )            
  11. HTML DSL HTML DSL HTML DSL HTML DSL HTML DSL

    HTML DSL HalogenはHTML DSL(ドメイン固有言語)を提供 HalogenはHTML DSL(ドメイン固有言語)を提供 HalogenはHTML DSL(ドメイン固有言語)を提供 HalogenはHTML DSL(ドメイン固有言語)を提供 HalogenはHTML DSL(ドメイン固有言語)を提供 HalogenはHTML DSL(ドメイン固有言語)を提供 HTML DSLにより,型安全なHTMLの宣言が可能 HTML DSLにより,型安全なHTMLの宣言が可能 HTML DSLにより,型安全なHTMLの宣言が可能 HTML DSLにより,型安全なHTMLの宣言が可能 HTML DSLにより,型安全なHTMLの宣言が可能 HTML DSLにより,型安全なHTMLの宣言が可能 前スライドのコード例のHHはエレメントのプレフィックスで,H 前スライドのコード例のHHはエレメントのプレフィックスで,H 前スライドのコード例のHHはエレメントのプレフィックスで,H 前スライドのコード例のHHはエレメントのプレフィックスで,H 前スライドのコード例のHHはエレメントのプレフィックスで,H 前スライドのコード例のHHはエレメントのプレフィックスで,H Pはプロパティ,HEはイベントハンドラ Pはプロパティ,HEはイベントハンドラ Pはプロパティ,HEはイベントハンドラ Pはプロパティ,HEはイベントハンドラ Pはプロパティ,HEはイベントハンドラ Pはプロパティ,HEはイベントハンドラ エレメント関数の一般形は下記の通り エレメント関数の一般形は下記の通り エレメント関数の一般形は下記の通り エレメント関数の一般形は下記の通り エレメント関数の一般形は下記の通り エレメント関数の一般形は下記の通り elementName elementName [ [ ... ... properties properties ... ... ] ] [ [ ... ... children children ... ... ] ]                        
  12. クエリ評価 クエリ評価 クエリ評価 クエリ評価 クエリ評価 クエリ評価 クエリ代数の動作を定義 クエリ代数の動作を定義 クエリ代数の動作を定義 クエリ代数の動作を定義

    クエリ代数の動作を定義 クエリ代数の動作を定義 eval eval :: :: TaskQuery TaskQuery ~> ~> H.ComponentDSL H.ComponentDSL Task Task TaskQuery TaskQuery TaskMessage TaskMessage m m eval eval ( (UpdateDescription UpdateDescription desc desc next next) ) = = do do CMS.modify CMS.modify ( (_ _ { { description description = = desc desc } }) ) pure pure next next eval eval ( (ToggleCompleted ToggleCompleted b b next next) ) = = do do CMS.modify CMS.modify ( (_ _ { { completed completed = = b b } }) ) H.raise H.raise ( (Toggled Toggled b b) ) pure pure next next ... ...      
  13. コンポーネント定義 コンポーネント定義 コンポーネント定義 コンポーネント定義 コンポーネント定義 コンポーネント定義 これまでの定義をまとめてコンポーネントを定義 これまでの定義をまとめてコンポーネントを定義 これまでの定義をまとめてコンポーネントを定義 これまでの定義をまとめてコンポーネントを定義

    これまでの定義をまとめてコンポーネントを定義 これまでの定義をまとめてコンポーネントを定義 task task :: :: forall forall m m. . Task Task -> -> H.Component H.Component HH.HTML HH.HTML TaskQuery TaskQuery Unit Unit TaskM TaskM essage essage m m task task initialState initialState = = H.component H.component { { initialState initialState: : const const initialState initialState , , render render , , eval eval , , receiver receiver: : const const Nothing Nothing } } where where      
  14. コンポーネントの実行 コンポーネントの実行 コンポーネントの実行 コンポーネントの実行 コンポーネントの実行 コンポーネントの実行 module module Main Main

    where where import import Prelude Prelude import import Control.Monad.Eff Control.Monad.Eff ( (Eff Eff) ) import import Halogen.Aff Halogen.Aff as as HA HA import import Halogen.VDom.Driver Halogen.VDom.Driver ( (runUI runUI) ) import import Component.List Component.List ( (list list) ) main main :: :: Eff Eff ( (HA.HalogenEffects HA.HalogenEffects ( () )) ) Unit Unit main main = = HA.runHalogenAff HA.runHalogenAff do do body body <- <- HA.awaitBody HA.awaitBody runUI runUI list list unit unit body body 14 / 47
  15. プログラムの構成 プログラムの構成 プログラムの構成 プログラムの構成 プログラムの構成 プログラムの構成 Main.purs Main.purs Main.purs Main.purs

    Main.purs Main.purs main() main() main() main() main() main() Model.purs Model.purs Model.purs Model.purs Model.purs Model.purs type Task, initialTask, type List, initialList() type Task, initialTask, type List, initialList() type Task, initialTask, type List, initialList() type Task, initialTask, type List, initialList() type Task, initialTask, type List, initialList() type Task, initialTask, type List, initialList() Component/List.purs Component/List.purs Component/List.purs Component/List.purs Component/List.purs Component/List.purs data ListQuery, newtype TaskSlot, data ListQuery, newtype TaskSlot, data ListQuery, newtype TaskSlot, data ListQuery, newtype TaskSlot, data ListQuery, newtype TaskSlot, data ListQuery, newtype TaskSlot, list() list() list() list() list() list() Component/Task.purs Component/Task.purs Component/Task.purs Component/Task.purs Component/Task.purs Component/Task.purs data TaskQuery, data TaskMessage, data TaskQuery, data TaskMessage, data TaskQuery, data TaskMessage, data TaskQuery, data TaskMessage, data TaskQuery, data TaskMessage, data TaskQuery, data TaskMessage, task() task() task() task() task() task()                         15 / 47
  16. Thermiteの概要 Thermiteの概要 Thermiteの概要 Thermiteの概要 Thermiteの概要 Thermiteの概要 purescript-reactのラッパー purescript-reactのラッパー purescript-reactのラッパー purescript-reactのラッパー

    purescript-reactのラッパー purescript-reactのラッパー Reactの全機能を提供することより,よく使われるAPIに対してク Reactの全機能を提供することより,よく使われるAPIに対してク Reactの全機能を提供することより,よく使われるAPIに対してク Reactの全機能を提供することより,よく使われるAPIに対してク Reactの全機能を提供することより,よく使われるAPIに対してク Reactの全機能を提供することより,よく使われるAPIに対してク リーンなAPIを提供することを優先 リーンなAPIを提供することを優先 リーンなAPIを提供することを優先 リーンなAPIを提供することを優先 リーンなAPIを提供することを優先 リーンなAPIを提供することを優先 puresript-reactの上にシンプルなモデル-ビュー-アクションの抽象 puresript-reactの上にシンプルなモデル-ビュー-アクションの抽象 puresript-reactの上にシンプルなモデル-ビュー-アクションの抽象 puresript-reactの上にシンプルなモデル-ビュー-アクションの抽象 puresript-reactの上にシンプルなモデル-ビュー-アクションの抽象 puresript-reactの上にシンプルなモデル-ビュー-アクションの抽象 化を提供 化を提供 化を提供 化を提供 化を提供 化を提供                  
  17. Thermiteのコンポーネント構成要素 Thermiteのコンポーネント構成要素 Thermiteのコンポーネント構成要素 Thermiteのコンポーネント構成要素 Thermiteのコンポーネント構成要素 Thermiteのコンポーネント構成要素 Thermiteのコンポーネントは下記5つの要素で定義される Thermiteのコンポーネントは下記5つの要素で定義される Thermiteのコンポーネントは下記5つの要素で定義される Thermiteのコンポーネントは下記5つの要素で定義される

    Thermiteのコンポーネントは下記5つの要素で定義される Thermiteのコンポーネントは下記5つの要素で定義される アクションの型 アクションの型 アクションの型 アクションの型 アクションの型 アクションの型 状態の型 状態の型 状態の型 状態の型 状態の型 状態の型 初期状態 初期状態 初期状態 初期状態 初期状態 初期状態 レンダリング関数 レンダリング関数 レンダリング関数 レンダリング関数 レンダリング関数 レンダリング関数 アクション実行関数 アクション実行関数 アクション実行関数 アクション実行関数 アクション実行関数 アクション実行関数                              
  18. アクションの型・状態の型 アクションの型・状態の型 アクションの型・状態の型 アクションの型・状態の型 アクションの型・状態の型 アクションの型・状態の型 アクションの型 - ユーザがコンポーネントに対して行う操作を表 アクションの型

    - ユーザがコンポーネントに対して行う操作を表 アクションの型 - ユーザがコンポーネントに対して行う操作を表 アクションの型 - ユーザがコンポーネントに対して行う操作を表 アクションの型 - ユーザがコンポーネントに対して行う操作を表 アクションの型 - ユーザがコンポーネントに対して行う操作を表 す す す す す す 状態の型 - コンポーネントの内部状態を表す 状態の型 - コンポーネントの内部状態を表す 状態の型 - コンポーネントの内部状態を表す 状態の型 - コンポーネントの内部状態を表す 状態の型 - コンポーネントの内部状態を表す 状態の型 - コンポーネントの内部状態を表す data data TaskAction TaskAction = = ChangeCompleted ChangeCompleted Boolean Boolean | | RemoveTask RemoveTask type type Task Task = = { { completed completed :: :: Boolean Boolean , , description description :: :: String String } }            
  19. 初期状態 初期状態 初期状態 初期状態 初期状態 初期状態 initialTask initialTask :: ::

    String String -> -> Task Task initialTask initialTask s s = = { { completed completed: : false false, , description description: : s s } }
  20. レンダリング関数 レンダリング関数 レンダリング関数 レンダリング関数 レンダリング関数 レンダリング関数 レンダリング関数 - コンポーネントの現在の状態と属性に対応す レンダリング関数

    - コンポーネントの現在の状態と属性に対応す レンダリング関数 - コンポーネントの現在の状態と属性に対応す レンダリング関数 - コンポーネントの現在の状態と属性に対応す レンダリング関数 - コンポーネントの現在の状態と属性に対応す レンダリング関数 - コンポーネントの現在の状態と属性に対応す るHTMLドキュメントを生成 るHTMLドキュメントを生成 るHTMLドキュメントを生成 るHTMLドキュメントを生成 るHTMLドキュメントを生成 るHTMLドキュメントを生成 render render :: :: T.Render T.Render Task Task props props TaskAction TaskAction render render dispatch dispatch _ _ s s _ _ = = [ [ R.tr R.tr' ' <<< <<< map map ( (R.td R.td' ' <<< <<< pure pure) ) $ $ [ [ R.input R.input [ [ RP._type RP._type "checkbox" "checkbox" , , RP.className RP.className "checkbox" "checkbox" , , RP.checked RP.checked s s. .completed completed , , RP.title RP.title "Mark as completed" "Mark as completed" , , RP.onChange RP.onChange \ \e e -> -> dispatch dispatch ( (ChangeCompleted ChangeCompleted ( (u u nsafeCoerce nsafeCoerce e e      
  21. アクション実行関数 アクション実行関数 アクション実行関数 アクション実行関数 アクション実行関数 アクション実行関数 アクション実行関数 - 状態の更新と何らかの(非同期の)計算を行う アクション実行関数

    - 状態の更新と何らかの(非同期の)計算を行う アクション実行関数 - 状態の更新と何らかの(非同期の)計算を行う アクション実行関数 - 状態の更新と何らかの(非同期の)計算を行う アクション実行関数 - 状態の更新と何らかの(非同期の)計算を行う アクション実行関数 - 状態の更新と何らかの(非同期の)計算を行う performAction performAction :: :: T.PerformAction T.PerformAction eff eff Task Task props props TaskAction TaskAction performAction performAction ( (ChangeCompleted ChangeCompleted b b) ) _ _ _ _ = = void void do do _ _ <- <- T.modifyState T.modifyState id id T.modifyState T.modifyState ( (_ _ { { completed completed = = b b } }) ) performAction performAction _ _ _ _ _ _ = = pure pure unit unit      
  22. Spec Spec Spec Spec Spec Spec コンポーネントの仕様をSpecとして定義 コンポーネントの仕様をSpecとして定義 コンポーネントの仕様をSpecとして定義 コンポーネントの仕様をSpecとして定義

    コンポーネントの仕様をSpecとして定義 コンポーネントの仕様をSpecとして定義 taskSpec taskSpec :: :: forall forall eff eff props props. . T.Spec T.Spec eff eff Task Task props props TaskAction TaskAction taskSpec taskSpec = = T.simpleSpec T.simpleSpec performAction performAction render render where where -- Renders the current state of the component as a collection of -- Renders the current state of the component as a collection of React elemen React elemen ts ts. . render render :: :: T.Render T.Render Task Task props props TaskAction TaskAction ... ... -- Updates the state in response to an action. -- Updates the state in response to an action.      
  23. コンポーネントの実行 コンポーネントの実行 コンポーネントの実行 コンポーネントの実行 コンポーネントの実行 コンポーネントの実行 module module Main Main

    ( (main main) ) where where import import Prelude Prelude import import Components.TaskList Components.TaskList ( (initialTaskListState initialTaskListState, , taskList taskList) ) import import Control.Monad.Eff Control.Monad.Eff ( (Eff Eff) ) import import DOM DOM ( (DOM DOM) ) as as DOM DOM import import Thermite Thermite as as T T -- | The main method creates the task list component, and renders -- | The main method creates the task list component, and renders it to the document body. it to the document body. main main :: :: Eff Eff ( (dom dom :: :: DOM.DOM DOM.DOM) ) Unit Unit main main = = T.defaultMain T.defaultMain taskList taskList initialTaskListState initialTaskListState unit unit 23 / 47
  24. プログラムの構造 プログラムの構造 プログラムの構造 プログラムの構造 プログラムの構造 プログラムの構造 Main.purs Main.purs Main.purs Main.purs

    Main.purs Main.purs main() main() main() main() main() main() Data/Filter.purs Data/Filter.purs Data/Filter.purs Data/Filter.purs Data/Filter.purs Data/Filter.purs data Filter, showFilter() data Filter, showFilter() data Filter, showFilter() data Filter, showFilter() data Filter, showFilter() data Filter, showFilter() Components/TaskList.purs Components/TaskList.purs Components/TaskList.purs Components/TaskList.purs Components/TaskList.purs Components/TaskList.purs data TaskListAction, _TaskAction(), data TaskListAction, _TaskAction(), data TaskListAction, _TaskAction(), data TaskListAction, _TaskAction(), data TaskListAction, _TaskAction(), data TaskListAction, _TaskAction(), type TaskListState, type TaskListState, type TaskListState, type TaskListState, type TaskListState, type TaskListState, initialTaskListState(), _tasks(), initialTaskListState(), _tasks(), initialTaskListState(), _tasks(), initialTaskListState(), _tasks(), initialTaskListState(), _tasks(), initialTaskListState(), _tasks(), taskList() taskList() taskList() taskList() taskList() taskList() Components/Task.purs Components/Task.purs Components/Task.purs Components/Task.purs Components/Task.purs Components/Task.purs data TaskAction, type Task, initialTask(), data TaskAction, type Task, initialTask(), data TaskAction, type Task, initialTask(), data TaskAction, type Task, initialTask(), data TaskAction, type Task, initialTask(), data TaskAction, type Task, initialTask(), taskSpec() taskSpec() taskSpec() taskSpec() taskSpec() taskSpec()                         24 / 47
  25. Riotの概要 Riotの概要 Riotの概要 Riotの概要 Riotの概要 Riotの概要 Riotはカスタムタグをすべてのブラウザで実現 Riotはカスタムタグをすべてのブラウザで実現 Riotはカスタムタグをすべてのブラウザで実現 Riotはカスタムタグをすべてのブラウザで実現

    Riotはカスタムタグをすべてのブラウザで実現 Riotはカスタムタグをすべてのブラウザで実現 実行前にタグはJavaScriptに変換される 実行前にタグはJavaScriptに変換される 実行前にタグはJavaScriptに変換される 実行前にタグはJavaScriptに変換される 実行前にタグはJavaScriptに変換される 実行前にタグはJavaScriptに変換される ReactのJSXはJavaScriptの中にHTMLを記述する感じなのに対し ReactのJSXはJavaScriptの中にHTMLを記述する感じなのに対し ReactのJSXはJavaScriptの中にHTMLを記述する感じなのに対し ReactのJSXはJavaScriptの中にHTMLを記述する感じなのに対し ReactのJSXはJavaScriptの中にHTMLを記述する感じなのに対し ReactのJSXはJavaScriptの中にHTMLを記述する感じなのに対し て,RiotのカスタムタグはHTMLの中にJavaScriptを記述する感じ て,RiotのカスタムタグはHTMLの中にJavaScriptを記述する感じ て,RiotのカスタムタグはHTMLの中にJavaScriptを記述する感じ て,RiotのカスタムタグはHTMLの中にJavaScriptを記述する感じ て,RiotのカスタムタグはHTMLの中にJavaScriptを記述する感じ て,RiotのカスタムタグはHTMLの中にJavaScriptを記述する感じ ビューのライブラリ ビューのライブラリ ビューのライブラリ ビューのライブラリ ビューのライブラリ ビューのライブラリ Virtual DOMを使用していない Virtual DOMを使用していない Virtual DOMを使用していない Virtual DOMを使用していない Virtual DOMを使用していない Virtual DOMを使用していない 将来的には対応予定 将来的には対応予定 将来的には対応予定 将来的には対応予定 将来的には対応予定 将来的には対応予定                         25 / 47
  26. カスタムタグの例 カスタムタグの例 カスタムタグの例 カスタムタグの例 カスタムタグの例 カスタムタグの例 < <todo todo> >

    < <h3 h3> >{ opts.title } { opts.title }</ </h3 h3> > < <ul ul> > < <li li each each= ={ { items items } }> > < <label label class class= ={ { done done } }> > < <input input type type= =" "checkbox checkbox" " checked checked= ={ { done done } } onclick onclick= ={ { parent.t parent.t oggle oggle } }> > { title } { title } </ </label label> > </ </li li> > </ </ul ul> > ... ... < <script script> > completed: completed: 26 / 47
  27. カスタムタグの構文 カスタムタグの構文 カスタムタグの構文 カスタムタグの構文 カスタムタグの構文 カスタムタグの構文 HTMLが先に定義され,ロジックは<script>タグに書かれる HTMLが先に定義され,ロジックは<script>タグに書かれる HTMLが先に定義され,ロジックは<script>タグに書かれる HTMLが先に定義され,ロジックは<script>タグに書かれる

    HTMLが先に定義され,ロジックは<script>タグに書かれる HTMLが先に定義され,ロジックは<script>タグに書かれる <script>タグがない場合,JavaScriptは最後のHTMLタグの直後か <script>タグがない場合,JavaScriptは最後のHTMLタグの直後か <script>タグがない場合,JavaScriptは最後のHTMLタグの直後か <script>タグがない場合,JavaScriptは最後のHTMLタグの直後か <script>タグがない場合,JavaScriptは最後のHTMLタグの直後か <script>タグがない場合,JavaScriptは最後のHTMLタグの直後か ら始まると見なされる ら始まると見なされる ら始まると見なされる ら始まると見なされる ら始まると見なされる ら始まると見なされる カスタムタグは,空・HTMLだけ・JavaScriptだけでも可 カスタムタグは,空・HTMLだけ・JavaScriptだけでも可 カスタムタグは,空・HTMLだけ・JavaScriptだけでも可 カスタムタグは,空・HTMLだけ・JavaScriptだけでも可 カスタムタグは,空・HTMLだけ・JavaScriptだけでも可 カスタムタグは,空・HTMLだけ・JavaScriptだけでも可 コーテーションはオプション コーテーションはオプション コーテーションはオプション コーテーションはオプション コーテーションはオプション コーテーションはオプション <foo bar={ baz }> は <foo bar="{ baz }"> に変換される <foo bar={ baz }> は <foo bar="{ baz }"> に変換される <foo bar={ baz }> は <foo bar="{ baz }"> に変換される <foo bar={ baz }> は <foo bar="{ baz }"> に変換される <foo bar={ baz }> は <foo bar="{ baz }"> に変換される <foo bar={ baz }> は <foo bar="{ baz }"> に変換される this 変数は常に現在のタグのインスタンスを指す this 変数は常に現在のタグのインスタンスを指す this 変数は常に現在のタグのインスタンスを指す this 変数は常に現在のタグのインスタンスを指す this 変数は常に現在のタグのインスタンスを指す this 変数は常に現在のタグのインスタンスを指す クラス名のショートカット構文が使える クラス名のショートカット構文が使える クラス名のショートカット構文が使える クラス名のショートカット構文が使える クラス名のショートカット構文が使える クラス名のショートカット構文が使える class={ completed: done }はdoneが真のとき,class="complete class={ completed: done }はdoneが真のとき,class="complete class={ completed: done }はdoneが真のとき,class="complete class={ completed: done }はdoneが真のとき,class="complete class={ completed: done }はdoneが真のとき,class="complete class={ completed: done }はdoneが真のとき,class="complete d" としてレンダリングされる d" としてレンダリングされる d" としてレンダリングされる d" としてレンダリングされる d" としてレンダリングされる d" としてレンダリングされる                                     27 / 47
  28. プリプロセッサ プリプロセッサ プリプロセッサ プリプロセッサ プリプロセッサ プリプロセッサ type属性で,プリプロセッサを指定できる type属性で,プリプロセッサを指定できる type属性で,プリプロセッサを指定できる type属性で,プリプロセッサを指定できる

    type属性で,プリプロセッサを指定できる type属性で,プリプロセッサを指定できる < <script script type type= =" "coffee coffee" "> > # your coffeescript logic goes here # your coffeescript logic goes here </ </script script> > 現在、 現在、 現在、 現在、 現在、 現在、co ee co ee co ee co ee co ee co ee と と と と と と typescript typescript typescript typescript typescript typescript ・ ・ ・ ・ ・ ・es6 es6 es6 es6 es6 es6 ・ ・ ・ ・ ・ ・ none none none none none none を使用可能 を使用可能 を使用可能 を使用可能 を使用可能 を使用可能             28 / 47
  29. タグのスタイリング タグのスタイリング タグのスタイリング タグのスタイリング タグのスタイリング タグのスタイリング styleタグを含めることができる styleタグを含めることができる styleタグを含めることができる styleタグを含めることができる

    styleタグを含めることができる styleタグを含めることができる Riot.jsは自動的にその内容を<head>の最後に挿入する Riot.jsは自動的にその内容を<head>の最後に挿入する Riot.jsは自動的にその内容を<head>の最後に挿入する Riot.jsは自動的にその内容を<head>の最後に挿入する Riot.jsは自動的にその内容を<head>の最後に挿入する Riot.jsは自動的にその内容を<head>の最後に挿入する < <todo todo> > <!-- layout --> <!-- layout --> < <h3 h3> >{ opts.title } { opts.title }</ </h3 h3> > < <style style> > todo todo { { display display: : block block } } todo h3 todo h3 { { font-size font-size: : 120% 120% } } /** other tag specific styles **/ /** other tag specific styles **/ </ </style style> > </ </todo todo> >       29 / 47
  30. Scoped CSS Scoped CSS Scoped CSS Scoped CSS Scoped CSS

    Scoped CSS Scoped css Scoped css Scoped css Scoped css Scoped css Scoped css と と と と と と :scope 擬似クラス :scope 擬似クラス :scope 擬似クラス :scope 擬似クラス :scope 擬似クラス :scope 擬似クラス をすべてのブラウザで利用可能 をすべてのブラウザで利用可能 をすべてのブラウザで利用可能 をすべてのブラウザで利用可能 をすべてのブラウザで利用可能 をすべてのブラウザで利用可能 Riot.jsはJavaScriptで独自に実装 Riot.jsはJavaScriptで独自に実装 Riot.jsはJavaScriptで独自に実装 Riot.jsはJavaScriptで独自に実装 Riot.jsはJavaScriptで独自に実装 Riot.jsはJavaScriptで独自に実装 < <todo todo> > <!-- layout --> <!-- layout --> < <h3 h3> >{ opts.title } { opts.title }</ </h3 h3> > < <style style> > :scope :scope { { display display: : block block } } h3 h3 { { font-size font-size: : 120% 120% } } /** other tag specific styles **/ /** other tag specific styles **/ </ </style style> > </ </todo todo> >       30 / 47
  31. タグのマウント タグのマウント タグのマウント タグのマウント タグのマウント タグのマウント タグを作成したら,次のようにページ上でそれをマウント タグを作成したら,次のようにページ上でそれをマウント タグを作成したら,次のようにページ上でそれをマウント タグを作成したら,次のようにページ上でそれをマウント

    タグを作成したら,次のようにページ上でそれをマウント タグを作成したら,次のようにページ上でそれをマウント < <body body> > < <todo todo> ></ </todo todo> > < <script script src src= =" "riot.min.js riot.min.js" "> ></ </script script> > < <script script src src= =" "todo.js todo.js" " type type= =" "riot/tag riot/tag" "> ></ </script script> > < <script script> >riot riot. .mount mount( ('todo' 'todo') )</ </script script> > </ </body body> >       31 / 47
  32. DOM要素へのアクセス DOM要素へのアクセス DOM要素へのアクセス DOM要素へのアクセス DOM要素へのアクセス DOM要素へのアクセス Riotは,this.refsオブジェクトに続く Riotは,this.refsオブジェクトに続く Riotは,this.refsオブジェクトに続く Riotは,this.refsオブジェクトに続く

    Riotは,this.refsオブジェクトに続く Riotは,this.refsオブジェクトに続く ref属性を持つ要素 ref属性を持つ要素 ref属性を持つ要素 ref属性を持つ要素 ref属性を持つ要素 ref属性を持つ要素 へのアク へのアク へのアク へのアク へのアク へのアク セスと、ショートハンドとしてif="{...}"属性のような セスと、ショートハンドとしてif="{...}"属性のような セスと、ショートハンドとしてif="{...}"属性のような セスと、ショートハンドとしてif="{...}"属性のような セスと、ショートハンドとしてif="{...}"属性のような セスと、ショートハンドとしてif="{...}"属性のような プロパティ プロパティ プロパティ プロパティ プロパティ プロパティ メソッド メソッド メソッド メソッド メソッド メソッドを提供 を提供 を提供 を提供 を提供 を提供       32 / 47
  33. タグのライフサイクル タグのライフサイクル タグのライフサイクル タグのライフサイクル タグのライフサイクル タグのライフサイクル タグは次の一連の流れで作成される タグは次の一連の流れで作成される タグは次の一連の流れで作成される タグは次の一連の流れで作成される

    タグは次の一連の流れで作成される タグは次の一連の流れで作成される 1 1 1 1 1 1...... タグが構成される タグが構成される タグが構成される タグが構成される タグが構成される タグが構成される 2 2 2 2 2 2...... タグのJavaScriptロジックが実行される タグのJavaScriptロジックが実行される タグのJavaScriptロジックが実行される タグのJavaScriptロジックが実行される タグのJavaScriptロジックが実行される タグのJavaScriptロジックが実行される 3 3 3 3 3 3...... テンプレート変数が計算される テンプレート変数が計算される テンプレート変数が計算される テンプレート変数が計算される テンプレート変数が計算される テンプレート変数が計算される 4 4 4 4 4 4...... ページ上でタグがマウントされ, ページ上でタグがマウントされ, ページ上でタグがマウントされ, ページ上でタグがマウントされ, ページ上でタグがマウントされ, ページ上でタグがマウントされ,mount mount mount mount mount mountイベントが発火 イベントが発火 イベントが発火 イベントが発火 イベントが発火 イベントが発火       33 / 47
  34. タグのライフライクル タグのライフライクル タグのライフライクル タグのライフライクル タグのライフライクル タグのライフライクル タグがマウントされた後,テンプレート変数は次のように更新さ タグがマウントされた後,テンプレート変数は次のように更新さ タグがマウントされた後,テンプレート変数は次のように更新さ タグがマウントされた後,テンプレート変数は次のように更新さ

    タグがマウントされた後,テンプレート変数は次のように更新さ タグがマウントされた後,テンプレート変数は次のように更新さ れる れる れる れる れる れる 1 1 1 1 1 1...... イベントハンドラが呼び出された際に自動的に(イベントハンドラ イベントハンドラが呼び出された際に自動的に(イベントハンドラ イベントハンドラが呼び出された際に自動的に(イベントハンドラ イベントハンドラが呼び出された際に自動的に(イベントハンドラ イベントハンドラが呼び出された際に自動的に(イベントハンドラ イベントハンドラが呼び出された際に自動的に(イベントハンドラ 内で,e.preventUpdateをtrueにセットしない場合) 内で,e.preventUpdateをtrueにセットしない場合) 内で,e.preventUpdateをtrueにセットしない場合) 内で,e.preventUpdateをtrueにセットしない場合) 内で,e.preventUpdateをtrueにセットしない場合) 内で,e.preventUpdateをtrueにセットしない場合) 2 2 2 2 2 2...... this.update() this.update() this.update() this.update() this.update() this.update() が現在のタグインスタンス上で呼ばれたとき が現在のタグインスタンス上で呼ばれたとき が現在のタグインスタンス上で呼ばれたとき が現在のタグインスタンス上で呼ばれたとき が現在のタグインスタンス上で呼ばれたとき が現在のタグインスタンス上で呼ばれたとき 3 3 3 3 3 3...... this.update() this.update() this.update() this.update() this.update() this.update() が親タグあるいは、さらに上流のタグで呼ばれたと が親タグあるいは、さらに上流のタグで呼ばれたと が親タグあるいは、さらに上流のタグで呼ばれたと が親タグあるいは、さらに上流のタグで呼ばれたと が親タグあるいは、さらに上流のタグで呼ばれたと が親タグあるいは、さらに上流のタグで呼ばれたと き.更新は親から子への一方通行で流れる き.更新は親から子への一方通行で流れる き.更新は親から子への一方通行で流れる き.更新は親から子への一方通行で流れる き.更新は親から子への一方通行で流れる き.更新は親から子への一方通行で流れる 4 4 4 4 4 4...... riot.update() riot.update() riot.update() riot.update() riot.update() riot.update() が呼ばれたとき.ページ上のすべてのテンプレート が呼ばれたとき.ページ上のすべてのテンプレート が呼ばれたとき.ページ上のすべてのテンプレート が呼ばれたとき.ページ上のすべてのテンプレート が呼ばれたとき.ページ上のすべてのテンプレート が呼ばれたとき.ページ上のすべてのテンプレート 変数を更新 変数を更新 変数を更新 変数を更新 変数を更新 変数を更新 タグが更新されるたびに, タグが更新されるたびに, タグが更新されるたびに, タグが更新されるたびに, タグが更新されるたびに, タグが更新されるたびに,update update update update update update イベントが発火 イベントが発火 イベントが発火 イベントが発火 イベントが発火 イベントが発火             34 / 47
  35. ライフサイクルイベント ライフサイクルイベント ライフサイクルイベント ライフサイクルイベント ライフサイクルイベント ライフサイクルイベント 次のような手順で,様々なライフサイクルイベントについてタグ 次のような手順で,様々なライフサイクルイベントについてタグ 次のような手順で,様々なライフサイクルイベントについてタグ 次のような手順で,様々なライフサイクルイベントについてタグ

    次のような手順で,様々なライフサイクルイベントについてタグ 次のような手順で,様々なライフサイクルイベントについてタグ の中からリスナー登録可能 の中からリスナー登録可能 の中からリスナー登録可能 の中からリスナー登録可能 の中からリスナー登録可能 の中からリスナー登録可能 < <todo todo> > this.on('before-mount', function() { this.on('before-mount', function() { // before the tag is mounted // before the tag is mounted }) }) this.on('mount', function() { this.on('mount', function() { // right after the tag is mounted on the page // right after the tag is mounted on the page }) }) this.on('update', function() { this.on('update', function() { // allows recalculation of context data before the update // allows recalculation of context data before the update       35 / 47
  36. テンプレート変数 テンプレート変数 テンプレート変数 テンプレート変数 テンプレート変数 テンプレート変数 HTMLには,括弧で囲まれたテンプレート変数を挿入可能 HTMLには,括弧で囲まれたテンプレート変数を挿入可能 HTMLには,括弧で囲まれたテンプレート変数を挿入可能 HTMLには,括弧で囲まれたテンプレート変数を挿入可能

    HTMLには,括弧で囲まれたテンプレート変数を挿入可能 HTMLには,括弧で囲まれたテンプレート変数を挿入可能 { /* my_expression goes here */ } { /* my_expression goes here */ } テンプレート変数は属性かネストされたテキスト使用可能 テンプレート変数は属性かネストされたテキスト使用可能 テンプレート変数は属性かネストされたテキスト使用可能 テンプレート変数は属性かネストされたテキスト使用可能 テンプレート変数は属性かネストされたテキスト使用可能 テンプレート変数は属性かネストされたテキスト使用可能 <h3 id={ /* attribute_expression */ }> <h3 id={ /* attribute_expression */ }> { /* nested_expression */ } { /* nested_expression */ } </ </h3 h3> >             36 / 47
  37. 入れ子のタグ 入れ子のタグ 入れ子のタグ 入れ子のタグ 入れ子のタグ 入れ子のタグ 親タグ<account>と入れ子になったタグ<subscription>を定義 親タグ<account>と入れ子になったタグ<subscription>を定義 親タグ<account>と入れ子になったタグ<subscription>を定義 親タグ<account>と入れ子になったタグ<subscription>を定義

    親タグ<account>と入れ子になったタグ<subscription>を定義 親タグ<account>と入れ子になったタグ<subscription>を定義 < <account account> > < <subscription subscription plan plan= ={ { opts.plan opts.plan } } show_details show_details= =" "true true" " /> /> </ </account account> > < <subscription subscription> > < <h3 h3> >{ opts.plan.name } { opts.plan.name }</ </h3 h3> > var plan = opts.plan, // Get JS handle to options var plan = opts.plan, // Get JS handle to options show_details = opts.show_details show_details = opts.show_details var parent = this.parent // access to the parent tag var parent = this.parent // access to the parent tag </ </subscription subscription> >       37 / 47
  38. 入れ子のタグのマウント 入れ子のタグのマウント 入れ子のタグのマウント 入れ子のタグのマウント 入れ子のタグのマウント 入れ子のタグのマウント accountタグを plan設定オプションとともに,ページにマウント accountタグを plan設定オプションとともに,ページにマウント

    accountタグを plan設定オプションとともに,ページにマウント accountタグを plan設定オプションとともに,ページにマウント accountタグを plan設定オプションとともに,ページにマウント accountタグを plan設定オプションとともに,ページにマウント < <body body> > < <account account> ></ </account account> > </ </body body> > < <script script> > riot riot. .mount mount( ('account' 'account', , { { plan plan: : { { name name: : 'small' 'small', , term term: : 'monthly' 'monthly' } } } }) ) </ </script script> >       38 / 47
  39. 名前付き要素 名前付き要素 名前付き要素 名前付き要素 名前付き要素 名前付き要素 ref属性を持つ要素は this.refs の配下のコンテキストに自動的にリ ref属性を持つ要素は

    this.refs の配下のコンテキストに自動的にリ ref属性を持つ要素は this.refs の配下のコンテキストに自動的にリ ref属性を持つ要素は this.refs の配下のコンテキストに自動的にリ ref属性を持つ要素は this.refs の配下のコンテキストに自動的にリ ref属性を持つ要素は this.refs の配下のコンテキストに自動的にリ ンクされるため,JavaScriptから簡単にアクセス可能 ンクされるため,JavaScriptから簡単にアクセス可能 ンクされるため,JavaScriptから簡単にアクセス可能 ンクされるため,JavaScriptから簡単にアクセス可能 ンクされるため,JavaScriptから簡単にアクセス可能 ンクされるため,JavaScriptから簡単にアクセス可能 < <login login> > < <form form ref ref= =" "login login" " onsubmit onsubmit= ={ { submit submit } }> > < <input input ref ref= =" "username username" "> > < <input input ref ref= =" "password password" "> > < <button button ref ref= =" "submit submit" "> > </ </form form> > submit(e) { // grab above HTML elements submit(e) { // grab above HTML elements var form = this.refs.login, var form = this.refs.login, username = this.refs.username.value, username = this.refs.username.value, password = this.refs.password.value, password = this.refs.password.value,       39 / 47
  40. イベントハンドラ イベントハンドラ イベントハンドラ イベントハンドラ イベントハンドラ イベントハンドラ イベントハンドラは次のように定義される イベントハンドラは次のように定義される イベントハンドラは次のように定義される イベントハンドラは次のように定義される

    イベントハンドラは次のように定義される イベントハンドラは次のように定義される < <login login> > < <form form onsubmit onsubmit= ={ { submit submit } }> > ... ... </ </form form> > submit(e) { // this method is called when above form is submitte submit(e) { // this method is called when above form is submitte d d ... ... } } </ </login login> >       40 / 47
  41. イベントハンドラ イベントハンドラ イベントハンドラ イベントハンドラ イベントハンドラ イベントハンドラ on on on on

    on on で始まる属性(onclick, onsubmit, oninputなど)には,イベント で始まる属性(onclick, onsubmit, oninputなど)には,イベント で始まる属性(onclick, onsubmit, oninputなど)には,イベント で始まる属性(onclick, onsubmit, oninputなど)には,イベント で始まる属性(onclick, onsubmit, oninputなど)には,イベント で始まる属性(onclick, onsubmit, oninputなど)には,イベント が起きた際に呼ばれる関数を設定可能 が起きた際に呼ばれる関数を設定可能 が起きた際に呼ばれる関数を設定可能 が起きた際に呼ばれる関数を設定可能 が起きた際に呼ばれる関数を設定可能 が起きた際に呼ばれる関数を設定可能 この関数はテンプレート変数によって動的に定義可能 この関数はテンプレート変数によって動的に定義可能 この関数はテンプレート変数によって動的に定義可能 この関数はテンプレート変数によって動的に定義可能 この関数はテンプレート変数によって動的に定義可能 この関数はテンプレート変数によって動的に定義可能 < <form form onsubmit onsubmit= ={ { condition condition ? ? method_a method_a : : method_b method_b } }> >             41 / 47
  42. イベントオブジェクト イベントオブジェクト イベントオブジェクト イベントオブジェクト イベントオブジェクト イベントオブジェクト イベントハンドラは通常のイベントオブジェクトを第一引数に受 イベントハンドラは通常のイベントオブジェクトを第一引数に受 イベントハンドラは通常のイベントオブジェクトを第一引数に受 イベントハンドラは通常のイベントオブジェクトを第一引数に受

    イベントハンドラは通常のイベントオブジェクトを第一引数に受 イベントハンドラは通常のイベントオブジェクトを第一引数に受 け取る け取る け取る け取る け取る け取る 次のプロパティについては,ブラウザが異なっても動作するよう 次のプロパティについては,ブラウザが異なっても動作するよう 次のプロパティについては,ブラウザが異なっても動作するよう 次のプロパティについては,ブラウザが異なっても動作するよう 次のプロパティについては,ブラウザが異なっても動作するよう 次のプロパティについては,ブラウザが異なっても動作するよう 標準化されている 標準化されている 標準化されている 標準化されている 標準化されている 標準化されている e.currentTargetは、イベントハンドラが指定された要素を指す e.currentTargetは、イベントハンドラが指定された要素を指す e.currentTargetは、イベントハンドラが指定された要素を指す e.currentTargetは、イベントハンドラが指定された要素を指す e.currentTargetは、イベントハンドラが指定された要素を指す e.currentTargetは、イベントハンドラが指定された要素を指す e.targetはイベントの送信元エレメント e.targetはイベントの送信元エレメント e.targetはイベントの送信元エレメント e.targetはイベントの送信元エレメント e.targetはイベントの送信元エレメント e.targetはイベントの送信元エレメント e.whichはキーボードイベント(keypress、keyupなど)のキーコー e.whichはキーボードイベント(keypress、keyupなど)のキーコー e.whichはキーボードイベント(keypress、keyupなど)のキーコー e.whichはキーボードイベント(keypress、keyupなど)のキーコー e.whichはキーボードイベント(keypress、keyupなど)のキーコー e.whichはキーボードイベント(keypress、keyupなど)のキーコー ド ド ド ド ド ド e.itemはループの中でのみ有効で,現在の要素を指す e.itemはループの中でのみ有効で,現在の要素を指す e.itemはループの中でのみ有効で,現在の要素を指す e.itemはループの中でのみ有効で,現在の要素を指す e.itemはループの中でのみ有効で,現在の要素を指す e.itemはループの中でのみ有効で,現在の要素を指す                                     42 / 47
  43. 条件属性 条件属性 条件属性 条件属性 条件属性 条件属性 条件属性を使うと,条件によって要素を表示/非表示できる 条件属性を使うと,条件によって要素を表示/非表示できる 条件属性を使うと,条件によって要素を表示/非表示できる 条件属性を使うと,条件によって要素を表示/非表示できる

    条件属性を使うと,条件によって要素を表示/非表示できる 条件属性を使うと,条件によって要素を表示/非表示できる < <div div if if= ={ { is_premium is_premium } }> > < <p p> >This is for premium users only This is for premium users only</ </p p> > </ </div div> >       43 / 47
  44. ループ ループ ループ ループ ループ ループ ループはeach属性として実装されている ループはeach属性として実装されている ループはeach属性として実装されている ループはeach属性として実装されている

    ループはeach属性として実装されている ループはeach属性として実装されている < <todo todo> > < <ul ul> > < <li li each each= ={ { items items } } class class= ={ { done done } }> > < <input input type type= =" "checkbox checkbox" " checked checked= ={ { done done } }> > { title } { title } </ </li li> > </ </ul ul> > this.items = [ this.items = [ { title: 'First item', done: true }, { title: 'First item', done: true }, { title: 'Second item' }, { title: 'Second item' }, { title: 'Third item' } { title: 'Third item' }       completed: completed: 44 / 47
  45. コンテキスト コンテキスト コンテキスト コンテキスト コンテキスト コンテキスト 新しいコンテキストが配列の要素ごとに作られ,その親にはpare 新しいコンテキストが配列の要素ごとに作られ,その親にはpare 新しいコンテキストが配列の要素ごとに作られ,その親にはpare 新しいコンテキストが配列の要素ごとに作られ,その親にはpare

    新しいコンテキストが配列の要素ごとに作られ,その親にはpare 新しいコンテキストが配列の要素ごとに作られ,その親にはpare nt変数を通じてアクセス可能 nt変数を通じてアクセス可能 nt変数を通じてアクセス可能 nt変数を通じてアクセス可能 nt変数を通じてアクセス可能 nt変数を通じてアクセス可能 < <todo todo> > < <div div each each= ={ { items items } }> > < <h3 h3> >{ title } { title }</ </h3 h3> > < <a a onclick onclick= ={ { parent.remove parent.remove } }> >Remove Remove</ </a a> > </ </div div> > this.items = [ { title: 'First' }, { title: 'Second' } ] this.items = [ { title: 'First' }, { title: 'Second' } ] remove(event) { remove(event) { } } </ </todo todo> >       45 / 47
  46. ループとイベントハンドラ ループとイベントハンドラ ループとイベントハンドラ ループとイベントハンドラ ループとイベントハンドラ ループとイベントハンドラ イベントハンドラは配列の中の個別の要素に,event.itemでアク イベントハンドラは配列の中の個別の要素に,event.itemでアク イベントハンドラは配列の中の個別の要素に,event.itemでアク イベントハンドラは配列の中の個別の要素に,event.itemでアク

    イベントハンドラは配列の中の個別の要素に,event.itemでアク イベントハンドラは配列の中の個別の要素に,event.itemでアク セス可能 セス可能 セス可能 セス可能 セス可能 セス可能 remove関数の実装は下記の通り remove関数の実装は下記の通り remove関数の実装は下記の通り remove関数の実装は下記の通り remove関数の実装は下記の通り remove関数の実装は下記の通り remove remove( (event event) ) { { // ループ要素 // ループ要素 var var item item = = event event. .item item // 配列の中のインデックス // 配列の中のインデックス var var index index = = this this. .items items. .indexOf indexOf( (item item) ) // 配列から削除 // 配列から削除 this this. .items items. .splice splice( (index index, , 1 1) ) } }             46 / 47
  47. Halogen, Thermite, Riotコード量の Halogen, Thermite, Riotコード量の Halogen, Thermite, Riotコード量の Halogen,

    Thermite, Riotコード量の Halogen, Thermite, Riotコード量の Halogen, Thermite, Riotコード量の 比較 比較 比較 比較 比較 比較 Halogen Thermite Riot ソース(行) 205 243 60 コンパイル出力 (kB) 678 1,592 1.2 + 822 uglify-js後(kB) 178 651 1.0 + 25 47 / 47