在ClojureScript

时间:2018-08-13 19:32:07

标签: clojurescript

我是CojureScript的新手,因为几个月前我遇到了LISP痒,然后又将API迁移到Clojure,所以我很喜欢它。现在,我也想迁移前端,但这是我使用CLJS的第一周。

所以,我有这个功能:

(defn foo []
   (events/listen (gdom/getElement "icon-add") EventType.CLICK
      (fn [e] (.log js/console (str ">>> VALUE >>>>> "  e)))))

该功能在core.cljs文件中很好用,但是如果我将其移至users.cljs文件,并使用以下命令从核心名称空间中调用它:

(ns zentaur.core
  (:require [zentaur.users :as users]

(users/foo)

从未找到DOM元素“ icon-add”,而是收到错误消息:

Uncaught goog.asserts.AssertionError {message: "Assertion failed: Listener can not be null.", reportErrorToServer: true, 
在浏览器控制台中

。如果我将功能移回core.cljs,所有功能都会再次正常运行。然后我的问题是:如何将一个函数移至另一个NS并确保其可以正常工作?

更新

我注意到,如果我直接在users.cljs中调用侦听器:

(events/listen (gdom/getElement "icon-add") EventType.CLICK
   (fn [] (.log js/console (str ">>> events/listen in users ns"))))

(我的意思是说没有任何功能),一切正常,代码找到DOM元素。

第二次更新

非常感谢您的回答,但此问题看起来像是“编译时间”问题。所有的听众:

(events/listen (gdom/getElement "icon-add") EventType.CLICK foo-funct)

必须在第一次运行CLJS时加载。再次加载 ns 是一件“第二次”的事情,因此DOM无法访问。

3 个答案:

答案 0 :(得分:3)

在核心名称空间中,您需要require第二个名称空间:

(ns xyz.core
  (:require [xyz.users :as users] ))

(users/foo)  ; call the function

这假定您的代码布局为

src
src/xyz
src/xyz/core.cljs
src/xyz/users.cljs

在命名和对其他命名空间的引用方面,还需要进行各种权衡取舍some good ideas here

答案 1 :(得分:3)

用户名称空间是特殊的,因为它被设计为预加载的,并且仅用于开发。这也是您唯一一次看到没有父包的名称空间。我说这只是为了警告您不要使用user作为名称空间名称-这样做只会引起混乱-无论它是否具有父程序包。

您的问题似乎是events/listen的参数之一以某种方式返回了nil。您在gdom中是否有zentaur.users的要求,所以:[goog.dom :as gdom]

答案 2 :(得分:2)

Google Closure库会引发断言错误,因为您的侦听器功能(即listen的第三个参数是null)。

查看库的源代码it tries to wrap the third parameter into a Listener,并从this failed assertion for a truthy value生成错误字符串。

当我不小心在函数周围加上多余的括号时,我经常遇到类似的问题。实际上,这导致函数在声明后立即被调用。即使已声明的函数需要一个或多个参数,也可能会在没有警告的情况下发生。 ClojureScript在JS上运行,该JS在调用函数时不会检查Arity。由于您的侦听器的主体只是console.log,它返回null,因此您将尝试将null分配为侦听器。

您确实注意到您提供的代码示例在core.cljs中有效。确实,该示例没有显示任何明显的原因,在这种情况下该函数为null。将此函数复制粘贴到users.cljs时可能会出现一个小错误,例如,添加了额外的括号?