如何创建"选项对象"在Scala.Js?

时间:2014-10-29 18:39:16

标签: scala.js

在惯用JavaScript中,让函数接受"选项对象"作为最后一个参数。这是您通常放置所有选项/很少使用的参数的地方,例如

jQuery.ajax({
   url: "http://www.example.com/foo",
   success: function() {
      ..
   }
})

Scala.JS的当前文档使用Scala特征来命令表示options对象,但是当您必须创建选项时会导致问题,因为您无法将匿名类传递给JavaScript代码。

如何从Scala代码创建此类选项对象?

3 个答案:

答案 0 :(得分:12)

我们建议如下(如果您选择创建外观类型):

trait AjaxOptions extends js.Object {
  val url: String = js.native
  val success: js.Function0[Unit] = js.native
}

object AjaxOptions {
  def apply(url: String, success: js.Function0[Unit]): AjaxOptions = {
    js.Dynamic.literal(url = url, success = success).asInstanceOf[AjaxOptions]
  }
}

优点是类型不安全的强制转换包含在一个位置。此外,如果您决定向/ AjaxOptions添加/删除字段,您(希望)会考虑调整随播广告的apply方法。因此,typer将通知您必须更改调用的位置(而不是仅将新字段设置为undefined)。

请参阅What is the suggested way to instantiate a js.Object for API wrappers了解更多信息。

答案 1 :(得分:2)

我发现这是一种非常有效的方法:

val fooOptions = js.Dynamic.literal().asInstanceOf[FooOptions]
fooOptions.url = ...
fooOptions.bar = ...
jsFunc(..., fooOptions)

当然,这假设FooOptions特征已将字段声明为 var 。如果没有,你将不得不使用

val fooOptions = js.Dynamic.literal(
   url = ...,
   bar = ...,
)
jsFunc(..., fooOptions)

但这种类型不太安全。

如果您要声明自己的选项特征,还可以使用适当的应用方法添加配套对象:

trait FooOptions extends Js.Object {
   var foo: js.String = ???
   var bar: js.String = ???
}

object FooOptions {
   def apply(): FooOptions =
      js.Dynamic.literal().asInstanceOf[FooOptions]
}

这会使调用代码变得更漂亮:

val fooOptions = FooOptions()
fooOptions.foo = ...
fooOptions.bar = ...
jsFunc(..., fooOptions)

答案 2 :(得分:2)

自从Scala.js发展以来,我用当前的最佳实践修改了我的答案:

此时,您应该使用特征来描述选项对象,如下所示:

trait AjaxOptions extends js.Object {
  var url: String
  var success: UndefOr[js.Function0[Unit]] = js.undefined
}

UndefOr[T]表示"此字段可能包含T,或者可能是undefined&#34 ;;请注意,您要将其初始化为js.undefined,因此它们具有默认值。

然后,在呼叫站点,您只需覆盖您需要设置的值:

val ajaxResult = new AjaxOptions {
  url = "http://www.example.com/foo"
}

请注意花括号:您实际上是在这里创建AjaxOptions的匿名子类,它可以满足您的需要。您不会覆盖的任何字段(例如上面的success)将保留为undefined,因此库将使用其默认值。

旧答案:

这个问题很老了,但是因为人们仍然来到这里:

如果你有一个庞大而复杂的选项对象(比如jQuery UI类的典型),你可能想要使用JSOptionBuilder为它构建一个外观,它位于the jsext library中。 JSOptionBuilder并不是万能药,但它是构建和使用任意复杂选项对象的一个​​不太多的样板机制。