发布于 2026-01-06 4 阅读
0

深入剖析 JavaScript 导入语法!大家好!DEV 全球展示挑战赛,由 Mux 呈现:展示你的项目!

剖析 JavaScript 导入语法

打个招呼!

由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!

注:这是我之前关于解构赋值文章的后续。导入语法大量使用了解构赋值,这对于新手来说可能会非常令人困惑。如果觉得这篇文章难以理解,建议先阅读我的另一篇文章!

我们来聊聊如何在 Node 项目中导入依赖项。随着项目变得越来越复杂,你不可避免地会遇到类似这样的语法:

import React, { useState, useEffect } from 'react';
import { Link } from 'gatsby';
import Button from '@material-ui/core/Button';
import moment from 'moment';

import { Layout } from '../components';
Enter fullscreen mode Exit fullscreen mode

乍一看,这很简单。我们导入一些代码片段,准备在 React 组件中使用。不过,正如你可能已经猜到的,我之所以选择这四行代码,是因为每一行都独一无二。事实上,在我作为一名正在成长的 Node/React 开发者的道路上,我发现了把这四行代码全部搞砸的方法。

你肯定也会把事情搞砸,但这完全没关系!现在,我就是来帮忙的。

我们将按复杂程度逐一查看这些内容,我会尽力解释到底发生了什么,以及我在工作中思考导入问题的方式。

简单的导入语法——最简单的情况

import moment from 'moment';
Enter fullscreen mode Exit fullscreen mode

如果你用过 .Net 语言、Python、Ruby 或其他任何一种编程语言,这应该是你的第二天性。我在这里特别提一下,是因为我们当中有些人可能以前从未见过这种情况。

这里发生了什么事?

其实很简单。moment是一个 JavaScript 库,它已经包含在我们 Node 项目的 ` .node`或 ` package.json.node.js` 文件中。如果您是 Node 新手,还不熟悉 moment ,请点击此处了解更多信息dependenciesdevDependenciespackage.json

这行代码创建了一个对moment库中所有可用资源的引用,并将其放入一个变量中,以便我们可以访问它。'moment'引号内的部分告诉编译器要使用哪个库。另一部分moment加引号)是变量本身。因此,从这里开始,我们可以像访问文件中的任何其他变量一样访问 moment:

import moment from 'moment';
console.log(
  moment().get('year')
);
// 2019
Enter fullscreen mode Exit fullscreen mode

不为人知的部分

moment在幕后,这只是将库通过export default 其主文件提供的所有内容都放入一个变量中——而该变量可以具有我们想要的任何有效名称

这可能有点令人困惑,但如果你觉得这个名字更有意义,你完全可以这样做:

import ThatReallyUsefulDateLibrary from 'moment';
console.log(
  ThatReallyUsefulDateLibrary().get('year')
);
// 2019
Enter fullscreen mode Exit fullscreen mode

从库中的某个位置导入组件

接下来——这个稍微复杂一些的家伙:

import Button from '@material-ui/core/Button';
Enter fullscreen mode Exit fullscreen mode

这里我们<Button />@material-ui中获取组件。这很简单,但从 material-ui 项目的结构来理解可能会有所帮助。Material-ui 导出了很多很棒的东西,而且它们都按照逻辑分组组织起来。可以这样理解:

// material-ui exports
const muiExports = {
  core: {
    Button: () => {}, // some component
    TextField: () => {} // another useful component
    // and loads more
  }
}
Enter fullscreen mode Exit fullscreen mode

通过上面的导入语法Button,我们告诉编译器提供一个指向名为 `<output_name>` 的导出对象的引用Button,该对象位于@material-ui库的 `<output_name>` 目录下/core/Button。编译器本质上将其视为上面代码片段中的 JSON 对象。

关键在于——这意味着我们可以对其进行解构!😁。这种语法也适用于导入Button

import { Button } from '@material-ui/core';
Enter fullscreen mode Exit fullscreen mode

这也意味着我们可以在一行代码中导入多个文件!/core

import { Button, TextField} from '@material-ui/core';
Enter fullscreen mode Exit fullscreen mode

很酷吧?我知道这可能有点让人困惑,但请坚持下去。很快你就会明白了。接下来我们来看下一个例子:

通过解构导入库的子集

import { Link } from 'gatsby';

Enter fullscreen mode Exit fullscreen mode

搞定!现在应该很简单了。它Gatsby提供的其中一项功能就是他们的link组件。我们这里只需要导入这个组件就可以了。

重命名导入

但是,如果我们Link的项目中已经存在一个名为 `<component>` 的组件呢?或者,如果我们正在制作一个《塞尔达传说》的粉丝网站,而 `<component>`已经在某个我们无法重命名的组件或变量中定义好了呢?其实,在导入语句中重命名元素和在解构语句中重命名元素一样简单。我们可以像这样Link重命名同一个组件:gatsby

import { Link as GatsbyWebLink } from 'gatsby';

Enter fullscreen mode Exit fullscreen mode

我们还可以在一条语句中重命名一个或多个解构导入:

import { 
  Link as GatsbyWebLink,
  graphql as graphqlQuery,
  useStaticQuery
} from 'gatsby';

Enter fullscreen mode Exit fullscreen mode

小菜一碟!🍰

相对导入

还有一点需要注意——如果你在导入位置字符串中使用相对路径,编译器就知道该查找你导出的内容了:

import { Layout } from '../components';

Enter fullscreen mode Exit fullscreen mode

就像其他任何地方一样,你可以在这里随心所欲地组合和重命名内容:

import {
  Layout,
  Button as SuperButton
} from '../components';

Enter fullscreen mode Exit fullscreen mode

把所有东西整合起来

最好的并不总是最后出现的,但这确实是我今天要分享的最后一个例子:

import React, { useState, useEffect } from 'react';

Enter fullscreen mode Exit fullscreen mode

如果你一直在家跟着做,现在应该对这一切很熟悉了——我们从 `<lib>` 中获取了默认导出react,并将其放入了变量 `<variable>` 中react。我们还解构了来自同一库的 `<class>`useState和`<class> `。如果你在想“我们难道不能把它作为 `<class>` 的子类来访问吗?”,答案是——实际上,是的!useEffectuseStateReact

这完全合理。

const [loading, setLoading] = React.useState(false);

Enter fullscreen mode Exit fullscreen mode

……但打字和阅读起来都不如……

const [loading, setLoading] = useState(false);

Enter fullscreen mode Exit fullscreen mode

从执行角度来看,两者功能相同,但后者是按惯例使用的。

我想就是这样了。

我想应该是这样。事实证明,写这篇文章真的挺棘手的——导入文件的方法数不胜数,而且我可能漏掉了许多情况。这里展示的某些导入语法肯定会对性能和包大小产生影响。虽然这些都是实实在在的限制,而且会对应用程序的性能产生实际影响,但为了简洁起见,我决定把这些讨论留到以后再说。

还有一个不容忽视的问题:目前使用import 语句require()需要像 Babel 或 Webpack 这样的转译器。这又是一个极其复杂的领域,我不确定自己是否有能力在一篇博文中解释清楚。这也意味着我没有展示上述语法是如何与 Node.js 配合使用的。坦白说,这方面需要解释的内容实在太多了——未来 EcmaScript 和 Node.js 的改进将会使一切变得更好。

打个招呼!

和往常一样,如果我哪里说错了,请务必告诉我!给我发个消息吧@irreverentmike。我很想听听你的意见。👋

信用

本文封面照片的背景图来自Unsplash 网站Ricardo Viana。感谢您的精彩作品!

文章来源:https://dev.to/irreverentmike/picking-apart-javascript-import-syntax-e5o