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

欢迎!有关如何使用本站点的更多信息,请参阅关于 页面。

0
ClojureScript

ES6 有特殊的语法用于使用 "default" 导入,而目前在使用导入的 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
`

我建议将一个 {{:default}} 添加到 {{ns :require}}。

(: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 更加普及后,我们应该有一个方便的方式来正确引用 "default" 导出。

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

10 个回答

0

由:deraen

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

我尚未更新所需的规格验证错误。

0

评论者:dnolen

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

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

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

0

评论者:thheller

我不明白这个建议。默认导出没有名称,{{.default}}属性仅在转译器中用于互通。在实际的JS中,使用的是活跃的引用。你将如何将{{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 而不是普通的 :require + ^:macros 或 :refer (链接: ^:macro foo)),我认为可能存在一些我不太了解的细微差别,阻止了我实现它。有此类问题吗?

0
_由thheller发布的评论:

从实现的角度来看,我认为{{^:default}}提示似乎更加复杂。

在Java/JVM和Clojure中也没有default导入/导出的等效功能。即使在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) 。

注意,AIUI,因为default是ES3中的一个严格关键词,您需要设置以下编译器选项才能使其正常工作:

:language-out :ecmascript5

否则,default会被转换为default$

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

关于这个问题的“官方”修复已经在此记录: https://clojure.atlassian.net/browse/CLJS-3235

...