我想在我的window#postMessage
处理程序上匹配不同的事件,但我无法匹配本机特征。那么我怎么能解决这个问题:
@js.native
trait XY extends js.Object {
val x: AnyVal = js.native
val y: AnyVal = js.native
}
@js.native
trait DataEvent extends js.Object {
val c: String = js.native // chart
val s: String = js.native // dataSet
val d: XY = js.native // xy data
val x: Seq[XY] = js.native // eXtra data
}
object ChartApi extends JSApp {
def receiveMessage(event: Any): Unit = {
event match {
case DataEvent => ???
case _ => println("else")
}
println(s"lala $event")
}
def main(): Unit = {
// add window event handler
dom.window.addEventListener("message", (event: MessageEvent) => receiveMessage(event.data), false)
println("Hello world!")
}
}
我在不同的iframe中有不同的图表,我需要发送类似&#34的事件;添加此数据"或者"清除数据"通过postMessage。
答案 0 :(得分:1)
JS traits在运行时没有标识,这就是为什么你不能直接测试任意对象是否是JS特征的实例的原因。
相反,您需要采用JS方式,并测试是否存在唯一标识由特征表示的接口的字段,以及其他可能的选择。例如:
if (event.hasOwnProperty("d")) {
// it must be a DataEvent, because the alternatives do not have a 'd' field
val e = event.asInstanceOf[DataEvent]
...
} else {
...
}
通常,我们不喜欢这样做。因此,在具有这种类型的消息的消息传递协议中,我们通常具有明确的messageType
字段或类似的字段。如果您确保所有DataEvent
条消息都为messageType = "data"
字段,则可以执行以下操作:
if (event.messageType == "data") {
val e = event.asInstanceOf[DataEvent]
...
} else {
...
}
您可以对此进行编码"类型测试"在提取器中:
object DataEvent {
def unapply(event: Any): Option[DataEvent] =
if (event.messageType == "data") Some(event.asInstanceOf[DataEvent])
else None
}
然后你可以在模式匹配中使用:
event match {
case DataEvent(event) => ???
case _ => println("else")
}
最后,您可能需要考虑使用序列化/ pickle库来将所有消息作为案例类来处理。有关此类库的列表,请参阅https://www.scala-js.org/libraries/libs.html。