YD's blog

Posted 四 04 8月 2016

Scala.js Tutorial

Setup

project/plugins.sbt 🔧

addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.10")

build.sbt 🔧

enablePlugins(ScalaJSPlugin)
name := "Scala.js Tutorial"
scalaVersion := "2.11.7" // or any other Scala version >= 2.10.2

並確認 project/build.properties 中的版本>=0.13.7


建立JSApp流程:

使用JSApp

src/main/scala/tutorial/webapp/TutorialApp.scala 🔧

package tutorial.webapp

import scala.scalajs.js.JSApp

object TutorialApp extends JSApp {
  def main(): Unit = {
    println("Hello world!")
  }
}

接著在 sbt 下 執行:

作者建議用 Node.js 解釋器,將 build.sbt 加入下列指令

scalaJSUseRhino in Global := false

建立html模板

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>The Scala.js Tutorial</title>
  </head>
  <body>
    <!-- Include Scala.js compiled code -->
    <script type="text/javascript" src="./target/scala-2.11/scala-js-tutorial-fastopt.js"></script>
    <!-- Run tutorial.webapp.TutorialApp -->
    <script type="text/javascript">
      tutorial.webapp.TutorialApp().main();
    </script>
  </body>
</html>

生成 JS File


實作1: 使用DOM

project/plugins.sbt 🔧

logLevel := Level.Warn
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.10")

build sbt 🔧

enablePlugins(ScalaJSPlugin)

name := "basicScalajs"

version := "1.0"

scalaVersion := "2.11.8"

scalaJSUseRhino in Global := false//Rhino is terribly slow. This will enable Node.js by default when launching sbt.

libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "0.9.0" //%%% means not a normal Scala library

src/main/scala/tutorial/webapp/TutorialApp.scala 🔧

package tutorial.webapp
import scala.scalajs.js.JSApp
import org.scalajs.dom
import dom.document
import scala.scalajs.js.annotation.JSExport

object TutorialApp extends JSApp {
  def appendPar(targetNode: dom.Node, text: String): Unit = {
    val parNode = document.createElement("p")
    val textNode = document.createTextNode(text)
    parNode.appendChild(textNode)
    targetNode.appendChild(parNode)
  }
  @JSExport //making scala.js method callable from JS
  def addClickedMessage(): Unit = {
    appendPar(document.body, "You clicked the button!")
  }
  def main(): Unit = {
    appendPar(document.body,"Hello World")
  }
}

接著在sbt 依序執行:

$reload //重新執行sbt
$run
$fastOptJS   //重新編譯js檔,但如果每次一有更動就要輸入嫌麻煩的話,執行 ~fastOptJS

根目錄下放置一個 html file(命名任意)

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>The Scala.js Tutorial</title>
</head>
<body>
<button id="click-me-button" type="button"
        onclick="tutorial.webapp.TutorialApp().addClickedMessage()">Click me!</button>
<!--Include Scala.js compiled code-->
<script type="text/javascript" src="./target/scala-2.11/basicscalajs-fastopt.js"></script>
<!-- Run tutorial.webapp.TutorialApp -->
<script type="text/javascript">tutorial.webapp.TutorialApp().main();</script>
</body>
</html>

實作2: 使用jQuery

project/plugins.sbt 🔧

enablePlugins(ScalaJSPlugin)

name := "basicScalajs"

version := "1.0"

scalaVersion := "2.11.8"

scalaJSUseRhino in Global := false//Rhino is terribly slow. This will enable Node.js by default when launching sbt.

libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "0.9.0" //%%% means not a normal Scala library

//jqueryVersion
libraryDependencies += "be.doeraene" %%% "scalajs-jquery" % "0.9.0"

skip in packageJSDependencies := false
jsDependencies +=
  "org.webjars" % "jquery" % "2.1.4" / "2.1.4/jquery.js"

jsDependencies += RuntimeDOM

src/main/scala/tutorial/webapp/TutorialApp.scala 🔧

import scala.scalajs.js.JSApp

import org.scalajs.jquery.jQuery

object TutorialApp extends JSApp {
  def addClickedMessage(): Unit = {
    jQuery("body").append("<p>You clicked the button!</p>")
  }
  def setupUI(): Unit = {
    jQuery("body").append("<p>Hello World</p>")
    jQuery("#click-me-button").click(addClickedMessage _)
  }
  def main(): Unit = {
    jQuery(setupUI _)
  }

html file

<button id="click-me-button" type="button">Click me!</button>
<!-- Include JavaScript dependencies -->
<script type="text/javascript" src="./target/scala-2.11/basicscalajs-jsdeps.js"></script>
<!-- Include Scala.js compiled code -->
<script type="text/javascript" src="./target/scala-2.11/basicscalajs-fastopt.js"></script>
<!-- Run tutorial.webapp.TutorialApp -->
<script type="text/javascript">tutorial.webapp.TutorialApp().main();</script>

接著 sbt 執行:

$reload
$run
$~fastOptJS

Full Optimization

Test and Automatically Creating Launcher

project/plugins.sbt 🔧

enablePlugins(ScalaJSPlugin)

name := "Scala.js Tutorial"

scalaVersion := "2.11.8"

libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "0.9.0"
libraryDependencies += "be.doeraene" %%% "scalajs-jquery" % "0.9.0"

skip in packageJSDependencies := false
jsDependencies +=
  "org.webjars" % "jquery" % "2.1.4" / "2.1.4/jquery.js"
jsDependencies += RuntimeDOM

// uTest settings
libraryDependencies += "com.lihaoyi" %%% "utest" % "0.3.0" % "test"
testFrameworks += new TestFramework("utest.runner.Framework")

//automatically creating a launcher
persistLauncher in Compile := true
persistLauncher in Test := false

src/test/scala/tutorial/webapp/TutorialApp.scala 🔧

package tutorial.webapp
import utest._
import org.scalajs.jquery.jQuery

/**
  * Created by YD on 2016/7/21.
  */

object TutorialTest extends TestSuite {

  // Initialize App
  TutorialApp.setupUI()

  def tests = TestSuite {
    'HelloWorld {
      assert(jQuery("p:contains('Hello World')").length == 1)
    }
    'ButtonClick {
      def messageCount =
        jQuery("p:contains('You clicked the button!')").length

      val button = jQuery("button:contains('Click me!')")//not yet click
      assert(button.length == 1)
      assert(messageCount == 0)

      for (c <- 1 to 5) {
        button.click()
        assert(messageCount == c)
      }
    }
  }
}

src/main/scala/tutorial/webapp/TutorialApp.scala 🔧

package tutorial.webapp

import scala.scalajs.js.JSApp

import org.scalajs.jquery.jQuery

object TutorialApp extends JSApp {
  def main(): Unit = {
    jQuery(setupUI _)
  }
  def setupUI(): Unit = {
    jQuery("body").append("<p>Hello World</p>")
    jQuery("""<button type="button">Click me!</button>""")
      .click(addClickedMessage _)
      .appendTo(jQuery("body"))
  }
  def addClickedMessage(): Unit = {
    jQuery("body").append("<p>You clicked the button!</p>")
  }
}

html file

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>The Scala.js Tutorial</title>
</head>
<body>
<!-- Include JavaScript dependencies -->
<script type="text/javascript" src="./target/scala-2.11/scala-js-tutorial-jsdeps.js"></script>
<!-- Include Scala.js compiled code -->
<script type="text/javascript" src="./target/scala-2.11/scala-js-tutorial-fastopt.js"></script>
<!--
&lt;!&ndash; Run tutorial.webapp.TutorialApp &ndash;&gt;
<script type="text/javascript">
      tutorial.webapp.TutorialApp().main();
    </script>-->
<!-- Run JSApp -->
<script type="text/javascript" src="./target/scala-2.11/scala-js-tutorial-launcher.js"></script>
</body>
</html>

Category: Scala
Tags: Scala