Scala.js 中对 JavaScript 的动态调用

Dynamic calls to JavaScript in Scala.js

我想知道如何在 Scala.js 中进行动态操作。例如,查看教程中的 jQuery 示例,我的理解是您在 scala 中定义了以下内容:

object TutorialApp extends JSApp {
  def appendPar(msg: String) = {
    jQuery("body").append("<p>" + msg + "</p>")
  }
  def main(): Unit = {
    appendPar("Hello World")
 }
}

这些都是编译时静态生成的东西。但是我没有看到任何可以动态设置消息参数的方法(例如从数据库中读取它)。

我不知道如何从数据库中读取它。这超出了这个问题的范围(或者你需要重新表述这个问题)。也许是 AJAX 电话之类的?

但是要从 <input> 标签中读取它,您需要这样做:

def main(): Unit = {
  val msg = jQuery("#myinput").value()
  appendPar(msg)
}

(虽然在这种情况下它在 main 方法中可能没有任何意义,但这不是重点。)

我的意思是,msg 只是一个 val(就像 JS 中的 var 但不可变)。您可以根据需要从任何动态信息源中获取它。

编辑:

如果你想在渲染页面时访问服务器动态生成的一些数据,你可以这样做:

首先,让您的服务器在生成的 HTML 中的 <script> 标记中将数据生成为全局 var。类似于:

<script type="text/javascript">
var mydata = {
  msg: "Some text generated dynamically by the server"
}
</script>

确保在 调用 Scala.js 的 main() 函数之前发出此脚本标记!

然后,从Scala.js,您可以使用js.Dynamic接口访问这些数据:

import scala.scalajs.js

val mydata = js.Dynamic.global.mydata
val msg = mydata.msg.asInstanceOf[String]

如果您的数据始终具有相对静态的结构,为它们声明您自己 a facade type 可能会有用:

@JSName("mydata")
object MyData extends js.Object {
  val msg: String = ???
}

然后你可以访问它而无需诉诸 Dynamic API:

val msg = MyData.msg

为它添加(并尝试概括): To call a javaScriptMethod on an object of a JavaScriptType you first write a type facade

import scala.scalajs.js
import scala.scalajs.js.annotation.JSName

@js.native
@JSName("JavaScriptType")
class MyType() extends js.Object {
  def javaScriptMethod(someParam: String) = js.native
}

之后,在客户端使用Scala的JavaScript代码就小菜一碟了:

val myObject = new MyType()
myObject.javaScriptMethod("Yippie")

作为一个具体示例,要在您的 Scala.js 应用程序中使用 Stack Overflow 的 Markdown converter Pagedown,您首先要为其创建类型外观:

@js.native
@JSName("Markdown.Converter")
class MarkdownConverter() extends js.Object {
  def makeHtml(txtUsingMarkdown: String): String = js.native
}

如果您正在使用 this great tutorial project 学习 Scala.js,您可以像这样在 Settings.scala 中声明对 Pagedown 的依赖:

val jsDependencies = Def.setting(Seq(
  "org.webjars.bower" % "pagedown" % "1.1.0" / "Markdown.Converter.js",
  //...

那么你可以简单地做

val html = new MarkdownConverter().makeHtml("this is *nice*")

这是我们调用 SparkMD5.

静态方法的另一个例子

我们定义了一个 object 而不是前面示例中的 class。此外,我们可以省略 @JSName 注释,因为我们的 Scala 类型与 JavaScript 类型同名:

@js.native
object SparkMD5 extends js.Object {
  def hash(str: String, raw: Boolean = false): String = js.native
}