React4sは、Frontend UIのScalaライブラリです。 FacebookのReactライブラリをラップします。コンポーネントのプレーンでシンプルなSCALAコードを簡単に記述できるようにするAPIを公開します。不可欠なshouldComponentUpdate()無料で取得します。コールバックメモは必要ありません。マクロ、関与、複雑なタイプはありません。
resolvers += Resolver .sonatypeRepo( " snapshots " )
libraryDependencies += " com.github.ahnfelt " %%% " react4s " % " 0.10.0-SNAPSHOT " case class OkCancel ( label : P [ String ]) extends Component [ Boolean ] {
override def render ( get : Get ) = E .div(
E .div( Text (get(label)),
E .div(
E .button(
Text ( " OK " ),
A .onClick(_ => emit( true ))
),
E .button(
Text ( " Cancel " ),
A .onClick(_ => emit( false ))
)
)
)
}これは、1つの文字列「Prop」という名前のlabelを撮影するコンポーネントOkCancel定義します。 get Objectを使用して小道具、状態などを読みます。これは、これらから安全に読むことができる場所でのみ利用可能です。 Boolean in Component[Boolean]には、このコンポーネントがemit(...)メソッドで行われるBooleanメッセージを排出していると述べています。 render()メソッドはコンポーネントをレンダリングするものであり、プロップまたは状態が変更されたときにコンポーネントが自動的にレンダリングされます。 E 、 A 、およびSオブジェクトは、仮想DOMを構築する方法を提供します。
小道具を介してコールバックを取り込む代わりにメッセージを放出することは、通常のReact APIからの逸脱であり、 shouldComponentUpdate()を無料で取得する方法です。また、入力(Props)を出力(コールバック)から明確に分離します。
このようなコンポーネントを使用できます: Component(OkCancel, "Would you like some icecream?") 。最初の引数は、コンポーネントコンパニオンオブジェクトです。残りの議論は、コンポーネントの小道具です。
case class Counter () extends Component [ NoEmit ] {
val okClicks = State ( 0 )
val cancelClicks = State ( 0 )
def onClick ( ok : Boolean ) = {
if (ok) {
okClicks.modify(_ + 1 )
} else {
cancelClicks.modify(_ + 1 )
}
}
override def render ( get : Get ) = E .div(
Component ( OkCancel , " Would you like some icecream? " ).withHandler(onClick),
E .hr(),
E .div( Text ( " You've clicked OK " + get(okClicks) + " times. " )),
E .div( Text ( " You've clicked Cancel " + get(cancelClicks) + " times. " ))
)
} Stateタイプにより、ライブラリは状態を更新するときに検出できるようにするため、コンポーネントを解決できます。 EGで読むことができます。 okClicks()とeegで更新します。 okClicks.set(42)またはokClicks.modify(_ + 1) 。
case class OkCancel ( label : P [ String ]) extends Component [ Boolean ] {
override def render ( get : Get ) = E .div(
E .div( Text (get(label)), S .color.rgb( 0 , 0 , 255 )),
E .div(
E .button(
FancyButtonCss ,
Text ( " OK " ),
A .onClick(_ => emit( true ))
),
E .button(
FancyButtonCss ,
Text ( " Cancel " ),
A .onClick(_ => emit( false ))
)
)
)
}上記では、1つのインラインスタイルのS.color.rgb(0, 0, 255)と1つのCSSクラスFancyButtonCss使用しています。 CSSクラスは次のように定義されています。
object FancyButtonCss extends CssClass (
S .cursor.pointer(),
S .border.px( 2 ).solid().rgb( 0 , 0 , 0 ),
S .color.rgb( 0 , 0 , 0 ),
S .backgroundColor.rgb( 255 , 255 , 255 ),
Css .hover(
S .color.rgb( 255 , 255 , 255 ),
S .backgroundColor.rgb( 0 , 0 , 0 )
)
)マウスがホバリングされているときに、黒い境界線を持つ白にし、黒いテキストを持つボタンをスタイリングします。結果の<style>...</style>は、 FancyButtonCssを使用してコンポーネントをレンダリングするために初めてDOMに追加されます。
object Main extends js. JSApp {
def main () : Unit = {
val component = Component ( Counter )
ReactBridge .renderToDomById(component, " main " )
}
}コンポーネントを作成して、 renderToDomByIdを呼び出すだけです。 "main"引数は、既存のHTML要素を参照するIDです。 <div id="main"></div> 。
Reactでは、モデルが更新されたときに無関係なコンポーネントを繰り返すことを避けるためにshouldComponentUpdate()を実装します。 React4Sでは、この方法はすでにあなたのために実装されています。 Scalaの!=オペレーターを使用して、プロップが変更されたかどうかを確認し、プロップが変更された場合、または状態が更新された場合にのみコンポーネントを更新します。つまり、再割り当てされていないすべてのものについては、参照を比較するだけで、小道具の奥深くに横断しないことを意味します。
小道具を介して通過したものは不変であり、構造的平等を持つ必要があることに注意してください。可変オブジェクトや機能を小道具として渡すことはできません。または、それぞれ古いビューまたはゆっくりしたビューを取得できます。ただし、不変のコレクションと不変のケースクラスを渡すことは完全に安全です。
これは、React4Sの完全なコンポーネントライフサイクルです。 React4Sモデルは、あなたの小道具が不変で構造的平等を持っているという仮定を立てているため、Plane Reactよりも簡単です。
Scalaの構造的不平等によって定義されているように、コンポーネントはあなたの小道具が変更されたときにのみrederendされます!= 、またはあなたの状態が更新されました。状態は、 update()を明示的に呼び出したときに更新されると見なされます。または!=演算子によると、以前とは異なる値を持つ状態オブジェクトの.set(...)または.modify(...)呼び出します。
これらのライフサイクルイベントでリッスンするアタッチブルを添付することができ、React4にはTimeout 、 Debounce 、 Loaderの3つが付属しています。オンラインの例でそれらがどのように使用されているかをご覧ください。