12

我正在尝试了解 clojurescript 中的命名空间模型。我知道 javascript 没有内置命名空间支持,所以它是通过 google 闭包库添加的。但是,我不明白 clojurescript 如何处理这些差异。有人可以解释一下吗?

例如,我想使用谷歌图表 api,并且尽可能想使用高级编译。我在closure/build调用中使用什么,ns表单看起来如何以及从代码中引用 api 的最佳方式是什么?我查看了https://github.com/sritchie/contour但该示例未使用高级编译,并且在 project.clj 文件中没有看到引用 google api 的选项。

4

1 回答 1

12

无论您使用的是简单模式还是高级模式编译,命名空间声明都是相同的。不同之处在于,不参与谷歌依赖管理的库goog.require('')需要goog.provide('')通过externs.js文件明确引用。您传递给 cljs 编译器的这个文件提供了所有变量和相关方法的存根。典型的externs.js看起来像:

// contents of externs.js
var externalLibrary = {}
var externalLibrary.method = function() {}

因此,要引用 google 闭包感知库,您的命名空间声明如下所示:

(ns my.namespace
  (:require  [goog.events.KeyCodes :as key-codes])

这会发出以下 javascript:

goog.provide("my.namespace");
goog.require("goog.events.keycodes");

请注意,如果您想从另一个 javascript 文件中调用您的闭包脚本,那么您需要将该方法标记为已导出,以便优化编译器知道保留该名称。(例如,您可能在要调用从 clojurescript 生成的 javascript 函数的页面上有一个脚本标记)

看起来像这样:

(defn ^:export externallyCalled [])

要注意的另一件事是,您必须在 clojurescript 中以不同的方式处理宏,这是因为在阅读器中“即时”处理它们的能力与在 clojure 中不同。

您可以按如下方式执行此操作(请注意,您必须使用 :as 在这种情况下绑定宏)

(ns my.namespace
   (:require-macros [my.macros :as my]))

如果你调用的代码没有参与谷歌的依赖管理,你可以通过js命名空间和 javascript 互操作访问它...

(. js/nonGoogle (method args)) ; a method access

(. js/nonGoogle -p)  ; a property access 

一切如常。变体也有效..

于 2012-03-15T17:12:34.473 回答