我使用 JSImport 编写了一个外观,并且它有效。不幸的是,我通过反复试验找到了解决方案,并且我不完全理解为什么这个特定的解决方案有效,但我尝试过的其他解决方案却无效。
背景:我从一个使用 sbt 构建的工作项目开始,它是一个单页应用程序,使用 scala.js 实现客户端代码,使用 scala 和 Play 框架实现服务器端代码。 javascript 库与 Web jar 一起打包,并使用 sbt jsDependency 变量捆绑到客户端 js 文件中。我想实现一些需要升级库的新功能,然后需要升级一些仅以 npm 格式提供的 javascript 库。所以现在我使用 npmDependency 和 scalajs-bundler 插件包含客户端应用程序的所有 javascript 依赖项。这破坏了一些 scalajs 外观,导致了我的问题。
我将使用门面log4javascript http://log4javascript.org/docs/manual.html#jsonlayout作为这个问题的一个例子。
变量log4javascript
是用于访问 api 其余部分的顶级对象。
当 js 库作为 Web jar 包含时,外观就是这样的log4javascript
已实施:
@js.native
@js.annotation.JSGlobalScope
object Log4JavaScript extends js.Object {
val log4javascript:Log4JavaScript = js.native
}
更改为 npm 后:
import scala.scalajs.js.annotation.JSImport.Namespace
@JSImport("log4javascript", Namespace)
@js.native
object Log4JavaScript extends js.Object {
def resetConfiguration(): Unit = js.native
def getLogger(name:js.UndefOr[String]): JSLogger = js.native
...
}
遵循 scala.jsdocs https://www.scala-js.org/doc/interoperability/facade-types.html为了编写导入模块,我期望对象名称(在本例中为 Log4JavaScript)必须与导出的符号名称匹配才能使绑定正常工作。然而,log4javascript.js 中的顶级符号是log4javascript
。经过实验,似乎 scala 对象名称对于绑定没有影响。无论我如何命名 scala 顶级对象,它都会正确绑定。
有人可以解释一下,当使用“命名空间”参数进行 JSImport 时,scala 对象/类/def/val 名称与 javascript 模块中的名称之间存在什么关系(如果有)?
根据 scala.js 文档,我似乎应该能够提供 js 对象的实际名称(我也尝试过“Log4JavaScript”)
@JSImport("log4javascript", "log4javascript")
@js.native
object SomeOtherName extends js.Object {
def resetConfiguration(): Unit = js.native
def getLogger(name:js.UndefOr[String]): JSLogger = js.native
...
}
然而,这无法绑定。当我尝试访问任何成员函数时,我会收到运行时错误。
Log4JavaScript.resetConfiguration()
Uncaught TypeError: Cannot read property 'resetConfiguration' of undefined
有人可以解释为什么这不起作用吗?
log4javascript 还在范围内定义了一些类log4javascript
。当 lib 作为 Web jar 包含时,定义如下所示:
@js.native
@JSGlobal("log4javascript.AjaxAppender")
class AjaxAppender(url:String) extends Appender {
def addHeader(header:String, value:String):Unit = js.native
}
切换到 npm 后,我必须将类定义放入顶级对象中:
@js.native
trait Appender extends js.Object {
...
}
@JSImport("log4javascript", "log4javascript")
@js.native
object Log4JavaScript extends js.Object {
...
class AjaxAppender(url: String) extends Appender {
def addHeader(name: String, value: String): Unit = js.native
}
...
}
这似乎很合理,但从 scala.js 文档来看,似乎应该可以在顶级对象之外以这种方式定义它
@JSImport("log4javascript", "log4javascript.AjaxAppender")
@js.native
class AjaxAppender(url: String) extends Appender {
def addHeader(name: String, value: String): Unit = js.native
}
然而,这也无法绑定。有人可以解释一下上面定义类的正确方法吗?或者定义嵌套在Log4JavaScript
反对唯一正确的方法吗?