Javascript 导入*作为从';反应;;vs导入从';反应;;

Javascript 导入*作为从';反应;;vs导入从';反应;;,javascript,reactjs,typescript,react-native,ecmascript-6,Javascript,Reactjs,Typescript,React Native,Ecmascript 6,我注意到,React可以这样导入: import*as React from'React'; …或者像这样: 从“React”导入React; 第一个导入react模块中的所有内容(请参阅:) 第二个只导入默认的模块导出(请参见:) 这两种方法似乎是不同的,根本不兼容 为什么他们都工作 请参考源代码并解释其机制…我有兴趣了解这是如何工作的 更新 这不是的副本 用ES6模块的一般信息回答了这个问题 我问的是使反应模块像这样工作的机制。它似乎与“hacky”导出机制有关,但不清楚如何将整

我注意到,
React
可以这样导入:


import*as React from'React';
…或者像这样:

从“React”导入React;

第一个导入
react
模块中的所有内容(请参阅:)

第二个只导入默认的模块导出(请参见:)


这两种方法似乎是不同的,根本不兼容

为什么他们都工作


请参考源代码并解释其机制…我有兴趣了解这是如何工作的


更新

这不是的副本

用ES6模块的一般信息回答了这个问题


我问的是使
反应
模块像这样工作的机制。它似乎与“hacky”导出机制有关,但不清楚如何将整个模块和默认导出到
React
中,并使这两种方法都能与传输JSX一起工作,等等。

您很可能有
的“allowSyntheticDefaultImports”:真的,
设置在
tsconfig.json
中,这实际上会关闭编译器认为无效的默认导入。Typescript添加了
esModuleInterop
,基本上实现了babel加载模块的功能

这允许您使用ES6默认导入,即使您正在导入的源代码没有将任何内容作为默认导出


在这个问题上,Typescript是严格的(遵循规则),这就是为什么它们要求您从“React”导入*as React。或者要求您告诉它允许在其基本配置中进行合成默认导入

TL;博士 事实上,ES导入语句
import default
import*
并不是一回事,在这种情况下,它们的行为是相同的,这是因为React作者选择在TypeScript(使用
esModuleInterop
)或Babel和您的绑定器中发布库和兼容层以使它们“正常工作”的组合. 根据ES6规范,它可能不应该工作,但今天我们仍然工作在一个JS模块乱七八糟的时代,所以Babel、TypeScript、Webpack等工具试图规范行为

更多详情: React不是ES6库。如果你看一下,你会在
index.js
中看到这一点:

const React = require('./src/React');

// TODO: decide on the top-level export form.
// This is hacky but makes it work with both Rollup and Jest.
module.exports = React.default || React;
(请注意注释,即使在React源代码中,它们也难以与ES6默认导出兼容性兼容。)

module.exports=
语法是CommonJS(NodeJS)。浏览器不会理解这一点。这就是为什么我们使用像Webpack、Rollup或packet这样的捆绑包。他们理解各种模块语法,并生成应该在浏览器中工作的包

但是,即使React不是ES库,TypeScript和Babel都允许您像导入ES库一样导入它(使用
import
语法,而不是
require()
,等等),但是CJS和ES之间存在着必须解决的差异。其中之一是,
export=
可以为您提供ES无法以符合规范的方式导入的内容,例如作为模块的函数或类。为了解决这些不兼容问题,Babel允许您导入CJS模块,就好像它们在默认情况下导出某些东西一样,或者作为名称空间导入。TypeScript有一段时间没有这样做,但最近在
esModuleInterop
下添加了这个选项。因此,现在Babel和TypeScript都可以非常一致地允许使用默认或命名空间ES导入CJS模块

对于TypeScript,它还取决于库的类型定义实际上是如何定义的。我不会深入讨论这个问题,但您可以想象这样的情况:由于Transpiler和Bundler,特定的导入在运行时工作,但TypeScript编译时不会出错

另一件值得一提的事情是,如果您查看React的构建代码,那么它有一个版本和CJS版本。UMD版本包含一些粗糙的运行时代码,试图使其在任何模块环境(包括浏览器)中工作。如果您只想在运行时包含React(即您不使用绑定器),则主要使用它


困惑?是的,我想是的

你问
为什么它们都能工作?
我问你,
为什么它们不能工作?
如果只导入默认值和所有内容,会得到相同的结果,你认为“所有内容”都意味着什么?您是否查看了要导入的源代码?
import*React from'React'包括
default
,我想。在类型脚本中,您可以在
tsconfig.json
中指定到
allowSyntheticDefaultImports
。这将允许您从“React”导入React
。Javascript/babel在这里“作弊”,允许您在实际不存在的情况下进行合成默认导入。导出
React
的正确语法应该是
import*,因为React from'React'
@KevinB我查看了源代码,似乎与之相关,但我不清楚它是如何工作的,这可以解释TypeScript,但它也适用于JavaScript,所以肯定还有其他原因。您在上面的评论中提到了
Babel
…JSX的
Babel
transpiler会做一些棘手的事情吗?@brian住在户外是的,Babel基本上是默认做的。实际上,正是
esModuleInterop
使这一功能得以实现。巴贝尔在处理模块时也做了类似的事情。模块有点乱,根据ES6规范
import default
import*
不应该是一回事,但通常情况下,它们在Transpiler和Bundler中可以互换,以避免混淆或不兼容。约翰,谢谢。在我接受之前,我会仔细阅读,但我