2024 年 Clojure 调查问卷 中分享你的想法!

欢迎!请参阅 关于 页面以了解更多关于此功能的信息。

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
`

我建议向 {{ns :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

评论由:deraan 撰写

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

我还没有更新要求规格的验证错误。

0

评论由:dnolen 发布

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

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

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

0

评论由:thheller 发布

我不理解这个建议。默认导出没有名字,{{.default}} 属性仅在互操作中由转换器使用。在实际的 JavaScript 中使用的是活引用。您如何将 {{RaisedButton}} 映射回 {{default}}?

{{["material-ui/RaisedButton" :default foo]}} 是有效的。JavaScript 模块可能实际上除了具有 {{code} export default ...},还具有 export { RaisedButton },这可能导致如果“猜测”错误名字时出现冲突。默认导出不是模块本身的别名,这是分开的。

我制作了一个引用转换表(链接: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
// 而必须使用 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 的引用,使其移入 NS 声明。这不是最优雅的解决方案,但可以完成任务,并且与全局导出一起工作:https://github.com/pesterhazy/cljs-spa-example/pull/14/files

注意,从我自己的理解来看,因为 default 在 ES3 中是一个严格的关键字,您需要设置以下编译器选项才能使这个方法工作:

:language-out :ecmascript5

否则,default 将会被更改成 default$

0
by
参考:[https://clojure.atlassian.net/browse/CLJS-2376](https://clojure.atlassian.net/browse/CLJS-2376)(由thheller报告)
0
by

这个问题的“官方”解决方案在这里有文档说明:[https://clojure.atlassian.net/browse/CLJS-3235](https://clojure.atlassian.net/browse/CLJS-3235)

...