2024 年 Clojure 状态调查中分享您的想法!

欢迎!请参阅关于页面以获得关于这是如何工作的更多信息。

0
ClojureScript by

ES6 有用于“默认”导入的特殊语法,而在使用导入的 ES6 代码时 CLJS 目前没有等效功能。

`
import * as 名称 from "模块名称";
(:require ["模块名称" :as 名称])

import { 导出 } from "模块名称";
(:require ["模块名称" :refer (导出)])

import { 导出 as 别名 } from "模块名称";
(:require ["模块名称" :refer (导出) :rename {导出 别名}])

import 默认导出 from "模块名称";
import 默认导出, { 导出 [ , [...] ] } from "模块名称";
import 默认导出, * as 名称 from "模块名称";
;; 无法轻松访问默认导出
`

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

(:require ["模块名称" :as mod :default foo])

这使得从 CLJS 使用重写的 ES6 代码变得更加方便。如果 "模块名称" 有默认导出,您目前必须在每处都写 {{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
by

注释由:deranen 制作

第一次实施想法。此实现将 {{:default 名称}} 重新写入 {{:refer [(default)} :rename {default 名称}}} 在最低级别({{parse-require-spec}}),因此我想其他函数不需要更改。

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

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 默认导出, * as 名称 from "模块名称";

(链接: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 (link: ^:macro foo)),我假设可能存在一些我不了解的细微差别,阻止了它的实现。有吗?

0
by
_评论者:thheller_

我觉得从实现角度来看,{{^:default}}提示似乎更复杂。

Java/JVM和Clojure中没有等效的默认导入/导出。甚至CommonJS中也没有等效功能。这完全是关于ES6。因此,将其附加到其他方法似乎是错误的。

在我看来,应该把它单独提出,因为使用{{.default}}属性并不完全正确,并且它的存在纯粹是为了兼容CommonJS。在严格的ES6中,这些并不作为由{{:as}}创建的"Object"的一部分存在。


;; 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
by

评论者:thheller

结果我发现我实际上是错误的。重新阅读了规范,{{.default}}确实定义为getter,因此它是可访问的。那么,之前的帖子就无需理睬了。

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

0
by

评论者:pesterhazy

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

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

请注意,根据我的理解,因为default在ES3中是一个严格的keyword,你需要设置以下编译器选项以使其工作:

:language-out :ecmascript5

否则,default会被修改为default$

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

关于此的“官方”修复方案在此处文档化: https://clojure.atlassian.net/browse/CLJS-3235

...