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

欢迎!请查看关于页面,了解如何使用本网站的更多信息。

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编译器(和用babbel重写的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

首次实施建议。此实现将{{:default name}}重写为{{:refer [default] :rename {default name}}}在最低级别({{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 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中没有默认导入/导出的等效功能。甚至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

我 encountered ES6 default exports,现在是常见的做法。人们在代码中遇到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
参考:https://clojure.atlassian.net/browse/CLJS-2376(由thheller报告)
0

针对此问题的“官方”修复方法已在以下文档中说明:https://clojure.atlassian.net/browse/CLJS-3235

...