我是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无法访问。
答案 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
时可能会出现一个小错误,例如,添加了额外的括号?