Scala.js事件处理



我正在编写一个使用两个事件处理程序的Scala.js应用程序:一个用于输入字段的onkeyup事件,另一个用于按钮的onclick事件。

两个事件处理程序共享很多常见的编码,但是一旦我尝试将事件处理程序编码优化到一个返回事件处理程序功能的单个函数中,它就会正确编译,但事件不再被困在浏览器。

在函数main中的以下代码中,btn.onclick的事件处理程序工作正常,但是cityNameInput.onkeyup的事件处理程序不再工作。我所做的只是将分配的编码直接复制到事件处理程序中,然后将其放置在返回Function1[dom.Event, _]keystrokeHandler函数中。这可以编译确定,但是onkeyup事件不再被困在浏览器中。

def keystrokeHandler(userInput: String, responseDiv: dom.Element): Function1[dom.Event,_] =
(e: dom.Event) => {
  // The city name must be at least 4 characters long
  if (userInput.length > 3) {
    responseDiv.innerHTML = ""
    val xhr = buildXhrRequest(userInput, searchEndpoint)
    xhr.onload = (e: dom.Event) => {
      val data: js.Dynamic = js.JSON.parse(xhr.responseText)
      // Can any cities be found?
      if (data.count == 0)
      // Nope, so show error message
        responseDiv.appendChild(p(s"Cannot find any city names starting with ${userInput}").render)
      else {
        // Build a list of weather reports
        buildSearchList(data, responseDiv)
      }
    }
    // Send XHR request to OpenWeather
    xhr.send()
  }
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Main program
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@JSExport
def main(container: dom.html.Div): Unit = {
  container.innerHTML = ""
  val cityNameInput = input.render
  val btn           = button.render
  val weatherDiv    = div.render
  cityNameInput.defaultValue = owmQueryParams.get("q").get
  btn.textContent            = "Go"
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  // Button onclick event handler
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  btn.onclick = (e: dom.Event) => {
    if (cityNameInput.value.length > 3) {
      weatherDiv.innerHTML = ""
      val xhr = buildXhrRequest(cityNameInput.value, weatherEndpoint)
      xhr.onload = (e: dom.Event) => {
        val data = js.JSON.parse(xhr.responseText)
        // Can the city be found?
        if (data.cod == "404")
        // Nope, so show error message
          weatherDiv.appendChild(p(s"City ${cityNameInput.value} not found").render)
        else {
          // So first add the div containing both the weather information
          // and the empty div that will hold the slippy map.
          // This is needed because Leaflet writes the map information to an
          // existing DOM element
          val report = new WeatherReportBuilder(data)
          weatherDiv.appendChild(buildWeatherReport(report, 0))
          buildSlippyMap("mapDiv0", report)
        }
      }
      // Send XHR request to OpenWeather
      xhr.send()
    }
  }
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  // Input field onkeyup event handler
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  cityNameInput.onkeyup = keystrokeHandler(cityNameInput.value, weatherDiv)
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  // Write HTML to the screen
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  container.appendChild(
    div(
      h1("Weather Report"),
      table(
        tr(td("Enter a city name (min 4 characters)"), td(cityNameInput)),
        tr(td(), td(style := "text-align: right", btn))
      ),
      weatherDiv
    ).render
  )
}

这里有什么问题?

keystrokeHandler功能是否应该返回一些特殊的Scala.js事件处理程序类型?还是其他东西?

谢谢

Chris W

我认为问题在这里:

cityNameInput.onkeyup = keystrokeHandler(cityNameInput.value, weatherDiv)

事件处理程序是触发的,但是在创建处理程序时,userInput被冷冻到cityNameInput.value ,而不是随cityNameInput.value的当前值而变化。确实,该线等同于

val userInput = cityNameInput.value
cityNameInput.onkeyup = keystrokeHandler(userInput, weatherDiv)

很明显cityNameInput.value仅评估一次。

相反,您应该将cityNameInput本身作为keystrokeHandler的参数,并在匿名函数内访问cityNameInput.value,以便每次调用函数(处理程序)时都会对其进行评估。

相关内容

  • 没有找到相关文章

最新更新