React4S是用于前端UI的Scala库。它包装了Facebook的React库。它揭示了一个API,使得为您的组件编写简单而简单的Scala代码变得易于使用。您可以免费获得必不可少的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 ))
)
)
)
}这定义了一个组件OkCancel ,该组件以一个名为label的字符串“ Prop”。您可以使用get对象阅读道具,状态等,只有可以安全地从中阅读的地方。 Component[Boolean]中的Boolean [Boolean]说,该组件会发出Boolean消息,这是用emit(...)方法完成的。 render()方法是渲染组件的方法,并且在道具或状态更改时会自动启动组件。 E , A和S对象提供了构建虚拟DOM的方法。
发出消息而不是通过道具接收回调是与通常的React API背道而驰,这是您免费获得shouldComponentUpdate()方式。它还清楚地将输入(Prop)与输出(回调)分开。
您可以使用这样的组件: 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()并使用EG进行更新。 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 ))
)
)
)
}上面使用一种内联样式S.color.rgb(0, 0, 255)和一个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 )
)
)它设计了一个按钮,是白色的,带有黑色边框,当鼠标悬停在鼠标上时,带有白色文本。首次使用FancyButtonCss渲染组件的结果<style>...</style>将被添加到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's !=操作员检查是否更改了任何道具,并且仅在更改了道具或状态已更新的情况下,仅更新组件。这意味着,对于所有尚未重新分配的内容,它只会比较参考文献,因此不会深入道具。
提防您通过道具通过的东西必须是不变的,并且具有结构平等。您不能将可变的对象或功能作为道具传递,也不能分别获得陈旧的视图或慢速视图。但是,通过不变的收藏和不变的案例类是完全安全的。
这是React4s的完整组成生命周期。它比普通的反应简单,因为React4s模型假设您的道具是不变并且具有结构性平等的。
只有在您的道具发生变化时,该组件才会被授予,如Scala的结构不平等!=所定义的,或者您的状态已更新。当您已明确调用update()或称为.set(...)或.modify(...)的状态对象上,该值与以前的!=不同时,该状态被考虑更新。
您可以将附加的附件附加在这些生命周期事件上,并且React4s随附其中三个: Timeout , Debounce和Loader 。查看它们在在线示例中的使用方式。