Clojurescript 添加一个事件监听器

Clojurescript Add an Event Listener

(defn domready [handler]
  (.addEventListener js/window "DOMContentLoaded" handler))

我从here那里借用了这段代码。问题是我不完全明白发生了什么。 JS 互操作对我来说仍然有点神秘。

  1. .addEventListener

所以这显然是一个过程调用,但它有点通用。这就像 Clojurescript 获取对象内部的所有内容,将其取出,然后使用它在 "objects" 上调用该方法。只要 "object" 有“.addEventListener” 属性 它就会调用它。这是它在做什么吗?为什么不使用关键字呢?像 (:addEventListener domElement) 这样对我来说更合乎逻辑。

  1. js/window

这是什么?它是命名空间还是对象?它们是一回事吗?

  1. "DOMContentLoaded"

一个字符串,很熟悉

  1. handler

也很熟悉,但有没有this的概念?并不是说我真的会想念 this.

.addEventListener 是对全局 Java 脚本对象 js/window 的方法调用。此方法调用有两个参数:"DOMContentLoaded"handler.

当您进行互操作(Java 或 Javascript)时,您实际上是在调用对象上的方法。这里发生的事情背后有宏。 ( 后面紧跟的是动词,我通常认为是函数调用(尽管它也可能是宏或特殊形式)。在进行互操作时,动词后面的是实例,然后是参数。

如果它是直接的 Java脚本,它将看起来像这样:

function domready(handler){
    window.addEventListener("DOMContentLoaded" handler);
}

.addEventListener

So this is clearly a procedure call, but it's kind of generic. It's like Clojurescript took everything that was inside an object, took it out, and you use it to call that method on "objects". As long as that "object" has the ".addEventListener" property it will call this. Is that what it's doing? Why not use a keyword instead? like (:addEventListener domElement) that seems more logical to me.

您关于其工作原理的心智模型基本没问题。它在编译时所做的是将函数名称移动为 运行 作为第一个参数的方法。

(.method obj ...args) 得到转换为 obj.method(...args)

这种类型的互操作来自父语言 Clojure。

关于为什么我们有一个调用函数的显式版本不是 Clojure 惯用的,我认为这个想法是明确区分原生 Clojure 代码和 Clojure 语义(不可变性、对 CLJ 数据结构友好等) ) 以及与主机环境互操作的内容(可变、对 CLJ 数据结构不友好等)。

在我看来,考虑到 CLJS 和主机平台的语义有多么不同,最好将这两者明确分开。对我来说,在这种情况下显式比隐式好(很容易发现代码是 CLJS 中的 JS 代码,什么是纯 CLJS)。

js/window

What is this? Is it a namespace or an object? Are they the same thing?

两者,js/ 正在访问命名空间 js,这是 CLJS 放置 JS 命名空间的地方(因为只有一个并且是全局的)。 window 只是从 js 命名空间中获取 window 变量。

这与您在 CLJS 中访问其他名称空间中的变量的方式没有什么不同。如果你 (def a 1)(ns cljs.test) 然后 运行 cljs.test/a 那会给你 1。同样的形式,ns/something-in-that-ns.

"DOMContentLoaded" A string, that's familiar.

\o/

handler

Also familiar, but does it have a notion of this? Not that I'm really going to miss this.

不确定 thishandler 有什么关系。它只是作为参数传递给 domready 的高阶函数,就像您在 JS 中所做的那样:function domready (onReady) { window.addEventListener("DOMContentLoaded", onReady) }


希望这对您有所帮助,如果您想现场试用并了解更多信息,可以访问 Talking with JS on the Diving into ClojureScript tutorial, or maybe check this section of the lt-cljs-tutorial

我只是在学习 clojurescript,所以我真的不知道它是否是正确的答案,但我是通过以下方式完成的:

(defn handler [] (js/console.log "ready"))
(js/document.addEventListener  "DOMContentLoaded" handler)

然后翻译成

cljs.user.handler = (function cljs$user$handler(){
  return console.log("ready");
});
document.addEventListener("DOMContentLoaded",cljs.user.handler);

检查我使用 KLIMPSE 的 clojurescript 如何翻译代码 http://app.klipse.tech/