在惯用JavaScript中,让函数接受"选项对象"作为最后一个参数。这是您通常放置所有选项/很少使用的参数的地方,例如
jQuery.ajax({
url: "http://www.example.com/foo",
success: function() {
..
}
})
Scala.JS的当前文档使用Scala特征来命令表示options对象,但是当您必须创建选项时会导致问题,因为您无法将匿名类传递给JavaScript代码。
如何从Scala代码创建此类选项对象?
答案 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并不是万能药,但它是构建和使用任意复杂选项对象的一个不太多的样板机制。