Binding.scala:如何在更新值时调用副作用?

时间:2018-02-26 00:01:56

标签: scala data-binding scala.js side-effects binding.scala

我的应用程序中有一个地理坐标列表,存储在Vars[Coordinates]中。我现在想在地图上显示这些内容,并在列表中添加或删除新坐标时自动更新地图。我正在使用一个公开API的库来添加和删除地图上的标记,所以我想在列表更新时调用它们,但我找不到任何明显的方法来做到这一点。关于如何实现这一目标的任何提示?

编辑:谢谢@杨波回复! 我最终得到了类似的东西:

val coordinates = Vars.empty[Coordinates]
def mapMountPoint(parent: Element, coordinates: BindingSeq[Coordinates]) =
  new MultiMountPoint[Coordinates](coordinates) {
    … // method overrides here to create the map in parent
  }
@dom 
def map = {
  val e = <div></div>
  mapMountPoint(e, coordinates).bind
  e
}

它似乎工作,当从DOM渲染或删除div时调用mount和unmount方法......但这是否真的应该如何完成呢?它看起来有点奇怪,我也会在编辑.bind时收到编译器警告:a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses

在monadic-html库中,有一种相当优雅的方式:

<canvas mhtml-onmount={ e => crazyCanvasStuff(e) }></canvas>

还有一个匹配的mhtml-onunmount属性用于清理。

2 个答案:

答案 0 :(得分:1)

您可能想要创建自己的MultiMountPoint,这会覆盖spliceset方法。

然后将挂载点注入渲染过程,类似于https://stackoverflow.com/a/45101054/955091

与Haskell不同,您可以在Scala中执行副作用,即使在HTML模板中也是如此。如果您写了类似<canvas id="my_canvas" data:dummy_attribute={ crazyCanvasStuff(my_canvas, coordinates.all.bind); "dummy_value" }></canvas>的内容,它也可以正常工作。

但是,执行副作用的其他解决方案建议,因为它们的行为取决于Binding.scala的内部实现。例如,当Binding.scala运行时发现上游数据未更改(Binding.scala router)时,可能无法重新评估副作用。使用挂载点是执行副作用的唯一正确方法,尤其是当您需要部分更新或者想要管理在渲染期间创建的自定义对象的生命周期时。

答案 1 :(得分:-1)

我用 https://github.com/rtimush/scalatags-rx

build.sbt: libraryDependencies + =&#34; com.timushev&#34; %%%&#34; scalatags-rx&#34; %&#34; 0.3.0&#34;

示例:如果按下按钮,则为机会颜色,使用scalatags ...

var colorActiv = "green"
var colorInActiv = "black"

val buttonDateColor = Var(colorInActiv) // big V in Var
val buttonDateRx = Rx(buttonDateColor())

...

def buttonDateOnclick(): Unit = {
    if (buttonDateColor.now == colorInActiv){
        buttonDateColor() = colorActiv
    } else {
        buttonDateColor() = colorInActiv
    }
}

... //在Menubuttons对象中:

var menuButtons =
div(
    button(
        menubuttonClass,
        color := buttonDateRx,
        onclick := buttonDateOnclick _,
        "button-text"
    )

... 在main / initialize()中:

dom.document.getElementById("buttonsdiv").appendChild(Menubuttons.menuButtons.render)