Mir ist aufgefallen, dass React
so importiert werden kann:
import * as React from 'react';
...oder wie folgt importieren:
import React from 'react';
Die erste Methode importiert den gesamten Inhalt des Moduls react
(siehe: Inhalte des gesamten Moduls importieren)
Die zweite Methode importiert nur den Modulexport default
(siehe: Standardexport importieren)
Die beiden Ansätze scheinen unterschiedlich und grundsätzlich unvereinbar zu sein.
Warum funktionieren sie alle?
Bitte sehen Sie sich den Quellcode an und erläutern Sie den Mechanismus ... Ich bin daran interessiert zu verstehen, wie das funktioniert.
Update
Dies ist keine doppelte Frage, sie unterscheidet sich von „dem Unterschied zwischen Import * as React from ‚React‘ und Import React From ‚React‘“
Diese Frage wird mit allgemeinen Informationen zum ES6-Modul beantwortet.
Ich frage nach dem Mechanismus, der es dem Modul react
ermöglicht, auf diese Weise zu funktionieren. Es scheint etwas mit einem „hackigen“ Exportmechanismus im Quellcode zu tun zu haben, aber es ist nicht klar, wie beide Möglichkeiten zum Importieren des gesamten Moduls und zum einfachen Importieren der Standardexporte in React
funktionieren mit transpiliertem JSX usw.
你的
tsconfig.json
文件中很可能设置了"allowSyntheticDefaultImports": true,
,这实际上让编译器对它认为无效的默认导入保持静默。Typescript 添加了esModuleInterop
,它基本上与 babel 在模块加载方面做的事情相同。这使你能够在导入的源代码没有默认导出时使用 ES6 默认导入。
Typescript 在这方面是严格的(遵循规则),这就是为什么它要求你使用
import * as React from 'react'
。或者要求你在基本配置中告诉它允许合成默认导入。更多相关信息
TL;DR
实际上,ES的import语句
import default
和import *
并不是同一回事,它们在这种情况下表现相同是因为React作者选择以这种方式发布库并在TypeScript(使用esModuleInterop
)或Babel以及打包工具中使用兼容层使其“正常工作”。根据ES6规范,它可能不应该正常工作,但是今天我们仍然处于JS模块混乱的时代,因此像Babel、TypeScript、Webpack等工具都试图规范行为。更多细节:
React不是一个ES6库。如果你查看源代码,你会在
index.js
中看到这个:(注意注释,即使在React源代码中,他们也在努力解决ES6默认导出的兼容性问题。)
module.exports =
语法是CommonJS(NodeJS)的语法。浏览器无法理解这个语法。这就是为什么我们使用像Webpack、Rollup或Parcel这样的打包工具。它们理解各种模块语法,并生成应该在浏览器中工作的打包文件。但是,尽管React不是一个ES库,但是TypeScript和Babel都允许你像导入ES库一样导入它(使用
import
语法,而不是require()
等),但是CJS和ES之间存在一些需要解决的差异。其中之一是export =
可以为你提供ES没有规范兼容的导入方式,比如将函数或类作为模块导入。为了解决这些不兼容性问题,Babel允许你以默认方式导入CJS模块,或者以命名空间方式导入。TypeScript以前不支持这样做,但是最近在esModuleInterop
下添加了这个选项。因此,现在Babel和TypeScript都可以相当一致地允许使用默认或命名空间ES导入来导入CJS模块。对于TypeScript来说,还取决于库的类型定义是如何定义的。我不会详细介绍,但你可以想象在某些情况下,由于转译器和打包工具的原因,特定的导入在运行时可以正常工作,但TypeScript在编译时会出现错误。
另一个值得一提的事情是,如果你查看React的构建代码,还有一个UMD模块版本以及CJS版本。UMD版本包含一些复杂的运行时代码,以使其在任何模块环境中(包括浏览器)正常工作。它主要用于在运行时仅包含React(即不使用打包工具)的情况下使用。示例。
令人困惑吗?是的,我也这么认为。:)