什么时候应该使用花括号进行 ES6 导入?

Posted

技术标签:

【中文标题】什么时候应该使用花括号进行 ES6 导入?【英文标题】:When should I use curly braces for ES6 import? 【发布时间】:2016-08-16 04:51:25 【问题描述】:

这似乎很明显,但我发现自己对何时使用花括号在 ES6 中导入单个模块感到有些困惑。例如,在我正在处理的 React-Native 项目中,我有以下文件及其内容:

文件 initialState.js

var initialState = 
    todo: 
        todos: [
            id: 1, task: 'Finish Coding', completed: false,
            id: 2, task: 'Do Laundry', completed: false,
            id: 2, task: 'Shopping Groceries', completed: false,
        ]
    
;

export default initialState;

在 TodoReducer.js 中,我必须在没有花括号的情况下导入它:

import initialState from './todoInitialState';

如果我将 initialState 括在花括号中,则以下代码行会出现以下错误:

无法读取未定义的属性 todo

文件TodoReducer.js

export default function todos(state = initialState.todo, action) 
    // ...

我的带有花括号的组件也会发生类似的错误。我想知道何时应该对单个导入使用花括号,因为很明显,在导入多个组件/模块时,您必须将它们括在花括号中,我知道。

here 的 Stack Overflow 帖子没有回答我的问题,而是我问什么时候我应该或不应该使用花括号来导入 single 模块,或者我不应该在 ES6 中使用花括号来导入单个模块(这显然不是这种情况,因为我已经看到需要花括号的单个导入)。

【问题讨论】:

using brackets with javascript import syntax的可能重复 不,不一样。谢谢 ES6 module export options 或 Javascript (ES6), export const vs export default 的可能副本 不,不一样。谢谢 如何判断导出是默认还是命名?例如reac-router-dom 包的链接?假设我已经安装了一个包并想要导入,我将如何知道是否使用 【参考方案1】:

这是一个默认导入

// B.js
import A from './A'

仅当A 具有默认导出时才有效:

// A.js
export default 42

在这种情况下,导入时分配给它的名称并不重要:

// B.js
import A from './A'
import MyA from './A'
import Something from './A'

因为它总是会解析为A默认导出


这是一个名为A命名导入:

import  A  from './A'

仅当A 包含一个名为A命名导出时才有效:

export const A = 42

在这种情况下,名称很重要,因为您要通过导出名称导入特定事物

// B.js
import  A  from './A'
import  myA  from './A' // Doesn't work!
import  Something  from './A' // Doesn't work!

要使这些工作,您需要将对应的命名导出添加到A

// A.js
export const A = 42
export const myA = 43
export const Something = 44

一个模块只能有一个默认导出,但命名导出任意数量(零个、一个、两个或多个)。您可以将它们全部导入:

// B.js
import A,  myA, Something  from './A'

在这里,我们将默认导出导入为A,并将导出命名分别称为myASomething

// A.js
export default 42
export const myA = 43
export const Something = 44

我们也可以在导入的时候给它们分配不同的名字:

// B.js
import X,  myA as myX, Something as XSomething  from './A'

默认导出往往用于您通常希望从模块中获得的任何内容。命名的导出往往用于可能很方便但并不总是必需的实用程序。但是,您可以选择如何导出内容:例如,一个模块可能根本没有默认导出。

This is a great guide to ES modules, explaining the difference between default and named exports.

【讨论】:

让一个模块有单独的导出 export const myA = 43; export const Something = 44;export default myA, Something 有什么坏处吗?因此,当您导入时,您可以import A from './A'; 获取模块中的所有内容,或者import Something from './A';,这样您只会获得模块中的一部分 很好,但是已经有一种语法可以将所有命名的导出抓取到一个对象中:import * as AllTheThings 这个怎么样 - import 'firebase/storage';import 'rxjs/add/operator/map';。那实际上是在做什么? @kyw:这会执行模块但忽略导出的值。对副作用有用。 注意:当您执行 const A = 42; export default A; 时,您不能执行 import A ; 这可能看起来很奇怪,并且在从命名导出重构为默认导出时可能会破坏您的导入(除非您删除花括号)。我想这有点合乎逻辑(叹气..),因为默认导出只导出一个值,而不是一个名称。 export default A 仅指 42 引用的值 A【参考方案2】:

我想说import ES6 关键字还有一个星号符号值得一提。

如果您尝试控制台记录 Mix:

import * as Mix from "./A";
console.log(Mix);

你会得到:

什么时候应该使用花括号进行 ES6 导入?

当您只需要模块中的特定组件时,括号是金色的,这使得 webpack 之类的打包器占用的空间更小。

【讨论】:

import * as Mix from "./A";import A as Mix from "./A"; 一样吗? 你所说的“加星标”是什么意思? Wild cards? @PeterMortensen term star, or starred 我相信我用了“*”thefreedictionary.com/starred 一个星号。那是 3 年前的事了,但我认为是这样。 @PeterMortensen 加星标表示使用开始符号并从该文件/模块导入所有内容【参考方案3】:

Dan Abramov's answer 解释了默认导出命名导出

使用哪个?

引用 David Herman:ECMAScript 6 支持单一/默认导出样式,并为导入默认值提供了最甜美的语法。导入命名导出可以甚至应该稍微不那么简洁。

但是,在 TypeScript 中,由于重构,命名导出受到青睐。例如,如果您默认导出一个类并重命名它,则类名将仅在该文件中更改,而在其他引用中不会更改,命名为导出的类名将在所有引用中重命名。 命名导出也是实用程序的首选。

总体使用你喜欢的任何东西。

附加

默认导出实际上是一个名为default的命名导出,所以默认导出可以导入为:

import default as Sample from '../Sample.js';

【讨论】:

Additional 行是很好的信息。如果您在没有定义像 export default 42 这样的名称的情况下导出,import A from './A' 没有意义。 请确保不要误解大卫赫尔曼的报价。这并不意味着“倾向于总是在 ES6 中使用单一/默认导出”,而是“因为单一导出如此普遍,ES6 最好支持默认值我们给了他们最甜蜜的语法".【参考方案4】:

如果您认为 import 只是 Node.js 模块、对象和 destructuring 的语法糖,我觉得它非常直观。

// bar.js
module = ;

module.exports = 
  functionA: () => ,
  functionB: ()=> 
;

 // Really all that is is this:
 var module = 
   exports: 
      functionA, functionB
   
  ;

// Then, over in foo.js

// The whole exported object:
var fump = require('./bar.js'); //=  functionA, functionB 
// Or
import fump from './bar' // The same thing - object functionA and functionB properties


// Just one property of the object
var fump = require('./bar.js').functionA;

// Same as this, right?
var fump =  functionA, functionB .functionA;

// And if we use ES6 destructuring:
var  functionA  =   functionA, functionB ;
// We get same result

// So, in import syntax:
import  functionA  from './bar';

【讨论】:

【参考方案5】:

总结ES6模块:

出口:

您有两种类型的导出:

    命名导出 默认导出,每个模块最多一个

语法:

// Module A
export const importantData_1 = 1;
export const importantData_2 = 2;
export default function foo () 

进口:

导出类型(即命名或默认导出)会影响导入内容的方式:

    对于命名导出,我们必须使用大括号和确切名称作为导出的声明(即变量、函数或类)。 对于默认导出,我们可以选择名称。

语法:

// Module B, imports from module A which is located in the same directory

import  importantData_1 , importantData_2   from './A';  // For our named imports

// Syntax single named import:
// import  importantData_1 

// For our default export (foo), the name choice is arbitrary
import ourFunction from './A';

感兴趣的事情:

    在大括号内使用逗号分隔的列表,并与命名导出的导出匹配名称。 使用您选择的不带花括号的名称进行默​​认导出。

别名:

当您想要重命名命名导入时,可以通过aliases 来实现。其语法如下:

import  importantData_1 as myData  from './A';

现在我们已经导入了importantData_1,但是标识符是myData而不是importantData_1

【讨论】:

【参考方案6】:

要想了解import语句中花括号的使用,首先要了解ES6中引入的destructuring的概念

>

    对象解构

    var bodyBuilder = 
      firstname: 'Kai',
      lastname: 'Greene',
      nickname: 'The Predator'
    ;
    
    var firstname, lastname = bodyBuilder;
    console.log(firstname, lastname); // Kai Greene
    
    firstname = 'Morgan';
    lastname = 'Aste';
    
    console.log(firstname, lastname); // Morgan Aste
    

    数组解构

    var [firstGame] = ['Gran Turismo', 'Burnout', 'GTA'];
    
    console.log(firstGame); // Gran Turismo
    

    使用列表匹配

      var [,secondGame] = ['Gran Turismo', 'Burnout', 'GTA'];
      console.log(secondGame); // Burnout
    

    使用扩展运算符

    var [firstGame, ...rest] = ['Gran Turismo', 'Burnout', 'GTA'];
    console.log(firstGame);// Gran Turismo
    console.log(rest);// ['Burnout', 'GTA'];
    

现在我们已经解决了这个问题,在 ES6 中,您可以导出多个模块。然后,您可以使用如下所示的对象解构。

假设您有一个名为module.js的模块

    export const printFirstname(firstname) => console.log(firstname);
    export const printLastname(lastname) => console.log(lastname);

您想将导出的函数导入index.js

    import printFirstname, printLastname from './module.js'

    printFirstname('Taylor');
    printLastname('Swift');

你也可以像这样使用不同的变量名

    import printFirstname as pFname, printLastname as pLname from './module.js'

    pFname('Taylor');
    pLanme('Swift');

【讨论】:

由于您正在展示与解构的比较,我将在您的最后一条评论中添加等效的解构比较:import printFirstname as pFname, printLastname as pLname from './module.js' 相当于:var foo = printFirstname: 'p_f_n', printLastname: 'p_l_n'; var printFirstname:pFname, printLastname: pLname = foo; pFname('Taylor'); pLname('Swift'); 健美爱好者? @TusharPandey 我是一名健美运动员 我认为在任何关于导入以及何时使用 curlys 与不使用它们的解释中,如果你没有提到对象破坏,那么你真的没有给出最好的解释。一旦我了解了解构,我就再也没有想过为什么要使用 curly,它只是直观地有意义。【参考方案7】:

通常在导出函数时需要使用 。

如果你有

export const x

你使用

import x from ''

如果你使用

export default const x

你需要使用

import x from ''

您可以在此处将 X 更改为您想要的任何变量。

【讨论】:

【参考方案8】:

花括号 () 用于导入命名绑定,其背后的概念是 destructuring assignment

关于 import 语句如何与示例一起工作的简单演示可以在我自己对 When do we use ' ' in javascript imports? 的类似问题的回答中找到。

【讨论】:

【参考方案9】:

大括号仅在命名导出时用于导入。如果导出为默认值,则不使用花括号进行导入。

【讨论】:

【参考方案10】:

对于默认导出,我们在导入时不使用 。

例如,

文件 player.js

export default vx;

文件 index.js

import vx from './player';

文件 index.js

文件 player.js

如果我们想导入我们导出的所有内容,那么我们使用*

【讨论】:

【参考方案11】:

如果文件中有任何默认导出,则不需要在导入语句中使用花括号。

如果文件中有多个导出,那么我们需要在导入文件中使用花括号,以便我们可以导入必要的。

您可以在下面的 YouTube 视频中找到使用花括号和默认语句的完全区别(非常重印度口音,包括滚动r 的...)。

21. ES6 Modules. Different ways of using import/export, Default syntax in the code. ES6 | ES2015

【讨论】:

以上是关于什么时候应该使用花括号进行 ES6 导入?的主要内容,如果未能解决你的问题,请参考以下文章

es6引用模块import后面加上花括号{}和不加花括号的区别

ES6,import时如何正确使用花括号'{ }'

每个[重复]的es6箭头函数中的花括号

关于if 要不要加括号

数组未在 C++ 中使用花括号进行初始化

在C语言中,if和else if是否在不加花括号的情况下也是一个复合语句