请在 Clojure 2024调查!中分享您的想法。

欢迎!请参阅关于页面以了解如何该工作的更多信息。

0
ClojureScript

ES6有特殊的语法用于使用"默认"导入,在导入ES6代码时,CLJS没有等效的语法。

`
import * as name from "module-name";
(:require ["module-name" :as name])

import { export } from "module-name";
(:require ["module-name" :refer (export)])

import { export as alias } from "module-name";
(:require ["module-name" :refer (export) :rename {export alias}])

import defaultExport from "module-name";
import defaultExport, { export [ , [...] ] } from "module-name";
import defaultExport, * as name from "module-name";
;; 无法轻松访问defaultExport
`

我建议在{{:require}}中添加一个{{:default}}。

(:require ["module-name" :as mod :default foo])

这使得从CLJS使用重写的ES6代码变得更加方便。如果"module-name"有一个默认导出,当前必须在每个地方都写{{mod/default}},因为没有简单的别名方式。

`
(:require ["material-ui/RaisedButton" :as RaisedButton])
;; :as是不正确的,现在用户必须使用
RaisedButton/default

(:require ["material-ui/RaisedButton" :default RaisedButton])
;; 允许直接使用
RaisedButton
`

内部,Closure编译器(以及由babel重写的ES6代码)会将默认导出重写到{{.default}}属性,所以{{:default}}真的只是一种方便访问它的方式。

已经工作很长时间的版本是

(:require ["material-ui/RaisedButton" :refer (default) :rename {default RaisedButton}])

当ES6更加普及时,我们应该有一个方便的方式来正确引用"默认"导出。

(链接:1) https://mdn.org.cn/en-US/docs/Web/JavaScript/Reference/Statements/import

10 答案

0

评论由:deraen作出的

首先是对实现方式的看法。此实现方式在最低级别({{parse-require-spec}})将{{:default name}}重写为{{:refer [default] :rename {default name}}}, 因此我认为其他函数无需更改。

我还没有更新require规范验证错误。

0

评论人:dnolen

在我看来,ES6默认导入的最理想语法如下

(:require ["material-ui/RaisedButton" :refer [RaisedButton]])

我不明白为什么我们不能让它工作?

0

评论人:thheller

我不明白那个建议。默认导出没有名字,{{.default}}属性仅在编译器互操作中用于。在实际情况中,使用一个活生生的引用。你怎么把{{RaisedButton}}映射回{{default}}?

{{["material-ui/RaisedButton" :default foo]}}是有效的。JS模块也可能实际上有一个export { RaisedButton },除了export default ...,如果你“猜测”的名字不正确将导致冲突。默认导出不是模块本身的别名,那是另外一回事。

我创建了一个引用翻译表(链接:1),添加{{:default}}别名的唯一方法才能可靠地映射所有ES6导入/导出功能。我看不出有什么方法可以使{{:refer}}正常工作,而不会非常不直观和不可靠。

import defaultExport, * as name from "module-name";

(链接:1) https://shadow-cljs.github.io/docs/UsersGuide.html#_using_npm_packages

0

评论人:dnolen

让我们在这个讨论中不摆出论调,集中关注技术细节。我只是不想在ns形式中包含另一个指令,并更倾向于避免这种方法的办法。从我个人的观点来看,我们还没有足够探索这种替代方案。

此批处理主要用于方便,我认为我们需要对此进行更多的思考,然后再决定任何事情。

0

评论人:jcr

为什么我们不能使用元数据来处理它呢?例如

(:require ["material-ui/RaisedButton" :refer [^:default RaisedButton]]) (:require ["module-name" :as mod :refer [^:default foo]]) (:require ["module-name" :refer [^:default foo, bar, baz]])

这不需要额外的ns指令,也不会造成任何歧义。

由于这没有用于宏(即我们没有:require-macros而不是 plain :require + ^:macros 或 :refer (链接:^:macro foo)),我假设可能有一些我还没有注意到的细微差别,阻止实施它。有吗?

0
由:thheller_ 收到的评论

对我来说,{{^:default}} 提示似乎在实现方面更为复杂。

在Java/JVM和Clojure中都没有默认导入/导出等效函数,在CommonJS中也没有。这完全是关于ES6的。因此,将其附加到“其他”方法上似乎是不正确的。

在我看来,应该将其分开的原因是因为使用 {{.default}} 属性并不是严格正确的,而且它的存在纯粹是为了与CommonJS的兼容性。在严格的ES6中,它们不是由 {{:as}} 创建的“对象”的一部分。


;; a.js
export let a = 1;
export let b = 2;
export default 3;

;; b.js
import x, * as y from "./a.js"

// 这些存在
y.a
y.b
// 在ES6中这不正确且不存在
y.default
// 取代 y.default,必须使用 x
x


鉴于CLJS目前不发出ES6,我们确实依赖{{.default}}属性的存在。但是,{{webpack}}已经更改了如何处理默认导出,我相信Closure Compiler在将来也会做类似的事情。
0

评论人:thheller

实际上我发现我错了。重新阅读规范后,{{.default}} 被定义为一个getter,因此它是可访问的。那么,我的前面的帖子就无关紧要了。

但这并没有改变我对 {{:default}} 作为更简单别名方法的有用性的看法。

0

由:pesterhazy 收到的评论

我遇到了ES6默认导出,这在当今很常见。人们在代码中遇到 default,例如:https://github.com/pesterhazy/cljs-spa-example/issues/13。我想报告我的发现。

如本问题的描述所述,您可以使用:refer:rename的组合来消除代码中对:default的引用,将其移动到命名空间声明中。这并不是最优雅的解决方案,但它完成工作并且可以与全局导出一起使用:https://github.com/pesterhazy/cljs-spa-example/pull/14/files

注意,根据我的理解,因为default在ES3中是严格的关键字,您需要设置以下编译器选项以使此方法有效

:language-out :ecmascript5

否则,default会被转换为default$

0
0

"官方"修复方案在此记录:https://clojure.atlassian.net/browse/CLJS-3235

...