【问题标题】:Binding.scala: How do I invoke side effects when a value is updated?Binding.scala:更新值时如何调用副作用?
【发布时间】:2018-08-05 09:28:57
【问题描述】:

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

edit:感谢@杨波的回复! 我最终得到了这样的结果:

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
}

它似乎工作,当 div 被渲染或从 DOM 中删除时调用 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 属性用于清理。

【问题讨论】:

  • 在 HTML 模板中调用副作用是危险的。我认为为副作用提供“优雅”的语法糖不是一个好主意。
  • 我不得不说我不同意。也许这很危险,但为了重用与 DOM 交互的库,这只是必要的,所以我认为它应该很简单。哦,好吧,这是你的项目 ;-)
  • MultiMountPoint 看起来像rarely used feature。你真的认为值得为此分配一个特殊的语法吗?
  • 它可能很少使用,但我认为它仍然是一个重要的功能。一个好的框架应该可以很容易地重用现有的库,我认为在数据绑定上下文中,这意味着我可以在要显示的数据发生变化时轻松调用 JavaScript API。
  • 您不需要特殊属性来执行副作用,请参阅stackoverflow.com/a/45101054/955091中的解决方案1

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


【解决方案1】:

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

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


与 Haskell 不同,您可以在任何地方在 Scala 中执行副作用,甚至在 HTML 模板中。如果你写了&lt;canvas id="my_canvas" data:dummy_attribute={ crazyCanvasStuff(my_canvas, coordinates.all.bind); "dummy_value" }&gt;&lt;/canvas&gt; 之类的东西,它应该也可以工作。

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

【讨论】:

    【解决方案2】:

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

    build.sbt: libraryDependencies += "com.timushev" %%% "scalatags-rx" % "0.3.0"

    示例:按下按钮时的机会颜色,使用 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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-14
      • 2023-01-09
      • 1970-01-01
      • 2018-06-29
      • 1970-01-01
      • 2010-10-29
      • 2021-08-04
      • 2018-01-30
      相关资源
      最近更新 更多