来自 clojure 时,clojurescript 的命名空间问题是什么? [英] What are the namespace gotchas for clojurescript when coming from clojure?

查看:13
本文介绍了来自 clojure 时,clojurescript 的命名空间问题是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to understand the namespacing model in clojurescript. I understand that javascript doesn't come built in with namespace support, so its been an add on via the google closure library. However, I don't understand how clojurescript deals with these differences. Can someone please explain?

例如,我想使用谷歌图表 api,并且在可能的情况下想使用高级编译.我在 closure/build 调用中使用什么,ns 形式是什么样的,从代码中引用 api 的最佳方式是什么?我看过 https://github.com/sritchie/contour 但那个例子没有使用高级编译,我在 project.clj 文件中看不到与 google api 相关的选项.

Lets say for example I want to use the google charts api and whenever possible would like to use advanced compilation. What do I use in the closure/build call, how would the ns form look like and what's the best way to refer to the api from the code? I've looked at https://github.com/sritchie/contour but that example doesn't use advanced compilation, and I don't see the options referring to the google api in the project.clj file.

推荐答案

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

The namespace declaration is the same regardless of whether you are using simple or advanced mode compilation. The difference is that libraries that don't participate in google dependency management via goog.require('') and goog.provide('') need to be explictly referenced via an externs.js file. This file, which you pass to the cljs compiler, provides stubs of all the vars and associated methods. A typical externs.js would look something like:

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

所以要引用谷歌闭包感知库,您的命名空间声明如下所示:

So to reference a google closure aware library your namespace declaration looks like this:

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

这会发出以下 javascript:

And that emits the following javascript:

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

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

Note that if you want to call your closurescript from another javascript file then you need to tag the method as exported so that the optimizing compiler knows to preserve the name. (e.g. you might have a script tag on a page from where you want to call a javascript function that has been generated from clojurescript)

看起来像这样:

(defn ^:export externallyCalled [])

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

The other thing to be aware of is that you have to treat macros differently in clojurescript, this is because the ability to process them 'on the fly' in the reader is not present in the same way as it is in clojure.

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

you do that as follows (note that you are obliged to bind the macros with :as in this case)

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

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

If you are calling code that didn't participate in google's dependency management you access it via the js namespace and the javascript interop...

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

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

一切正常.变体也有效..

all the usual . variants work too..

这篇关于来自 clojure 时,clojurescript 的命名空间问题是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆