序
上文 说到
Openlayers 6.2.1
开发环境的搭建,并简述了各个插件的功能。今天本文将继续记录关于Node
环境下OpenLayers
开发的小小心得。
问题总结
完成了 Openlayers
的环境搭建,接下来的任务就是功能开发。接下来,全文将记录博主在开发过程中所有遇到的跟 Node
相关的问题总结。
一、对关键字 import,export
的理解
import
和 export
作为 ES6
中新增的两个关键字,主要是用来解决作用域的问题。通常情况下 import
和 export
是成对使用的。即:假设我在 B.js
中定义了一个名为 str
的变量,如果想在其它 js
文件中也能使用,那么 B.js
文件中就必须使用 export
关键字将 str
导出。同时 A.js
文件也必须使用 import
关键字将 str
进行导入方可使用。
二、具体代码及相关问题
首先我们要在同一目录下创建以下三个文件:
A.js
import str from "./B";
import {bbb} from "./B";
// str = null;
document.write(str+bbb);
B.js
let str = "blablabla~";
let bbb = "NB";
export default str;
export {bbb}
index.html
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="A.js"></script>
</head>
<body>
</body>
</html>
启动项目 (这里博主用的 IDE
工具可在界面底部 Terminal
面板内直接敲命令)
npm start
项目启动后,如未修改过项目端口,则直接访问 http://localhost:1234
即可看到页面上的显示结果:
blablabla~NB
如果你已经看到了界面上显示的上述内容,说明你的项目 parcel
插件是没有问题的。
那么现在我们来分析一下代码:
1. 根据文件关系,我们先来看 B.js
文件,在这个文件中通过 let
关键字定义了变量 str
和 bbb
,并通过 export default
和 export {}
两种方式进行了变量导出操作。这里值得注意的是,用 export default
进行变量导出时,在一个 js
文件中只能出现一次也可以不出现。而 export {}
方式的导出可以将多个要导出的变量放入大括号内,并用逗号分开即可。
2. 在 A.js
文件中,前两行是对 B.js
中导出的变量的导入。第一行是对 export default
导出变量的导入方式,第二行是对 export {}
导出变量的导入方式,如果需要导入多个,只需在大括号内填入其他需要导入的变量名,并用逗号分开即可。这部分需要注意的是,不可将 export default
和 export {}
导出的变量合并到 import {} from
中一起导入。
3. 在 index.html
中,我们可以看到,这里只对 A.js
进行了引用,并未对 B.js
进行引用,然而代码却运行正常。这是因为我们所搭建的项目环境能够对入口文件(index.html
)与其他文件间的引用关系进行自动查找导入,不用我们进行手动的显式导入。
4. 现在我们再回过头来看 A.js
文件,第三行处有一句被我注释掉的代码。现在把它的注释去掉,让其运行。运行结果如下:
A.f5b0a0fa.js:116 Uncaught Error: "str" is read-only.
at A.js:3
at Object.parcelRequire.A.js../B (A.js:3)
at newRequire (A.f5b0a0fa.js:47)
at A.f5b0a0fa.js:81
at A.f5b0a0fa.js:120
这里可以看到由于我们在 A.js
文件中对 B.js
文件中的变量 str
进行了修改,导致了本次错误。错误原因为是:在 A.js
文件中 B.js
文件是只读的,换句话说,在 A.js
中我们是没有权限修改变量 str
所指向的内存地址的。
5. 接下来我们分别对 A.js
和 index.html
文件做一下内容的调整,修改后的代码如下:
A.js:
function onLoadTest() {
document.write("哎呦,不错呦~!");
}
index.html:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="A.js"></script>
</head>
<body onload="onLoadTest()">
</body>
</html>
修改完代码,我们在 Terminal
面板执行一下 npm start
命令,把项目启动一下,然而结果却让人“呵呵”。我们非但没有看到页面上 哎呦,不错呦~!
的称赞,浏览器还(口吐芬芳)给报了个错。
Uncaught ReferenceError: onLoadTest is not defined
at onload ((index):8)
onLoadTest
未定义?怎么会?明明就在 A.js
文件中定义过了啊?而且 html
中还引用了函数所在的文件呢~!(有人可能会说是因为没有用 export
进行变量导出,在这里我想说,我当时也这么想过,并进行了导出操作,运行结果可想而知——依然报错)换种打开方式试试,把 index.html
文件直接拖进打开的浏览器中,你看到了什么?屏幕上赫然写着: 哎呦,不错呦~!
。看到这里是不是更懵了?下面我来解释一下为什么会这样,并说一下这种问题改怎么处理。
会出现这样的问题是因为,在面向对象的模块化开发的模式下,我们在某个 js
文件中定义的函数或变量的作用域仅为当前文件,出了他们所在的文件,我们就无法直接调用了,所以就会报错。看到这里如果你又想到,那我就在 A.js
文件中把函数导出,在 index.html
中用 <script> import {XXX} from "XXX";</script>
把函数导入不就可以了吗?很开心我们再一次想到了一起,但遗憾的告诉你,这种导入方式是被浏览器禁止的,因此也行不通。那我们该怎么办?把 js
函数写到 html
里吗?如果真这么做的话,还真可以。可现实告诉我们这样的项目是不切实际的,因为一旦我们在 html
中嵌套了其他 js
文件中的函数,我们就又得导入,然后浏览器还是不允许这样的方式。死循环了~!
咋办?办法有一个,就是将动态或静态写在 html
节点中的被调用的函数设置成全局变量即可。也就是把需要被调用的函数放到全局作用域中,以使其在项目中任何一个文件中都可以被自由的调用。这里就又引出了浏览器和 Node
中的全局变量的问题。
浏览器中,最高层级的全局变量是 windows
,它包含了所有定义在所有 js
文件中的变量。而在 Node
中,最高层级的全局变量是 globa
,他们之间是有区别的,但这并不影响我们的使用,故而也就自然不是我们关注的重点。(别问有啥区别,问就是不会~!)既然全局变量有了,那我们要做的就是给这个变量增加一个属性的事了。修正后的代码如下:
A.js
global.onLoadTest = function () {
document.write("哎呦,不错呦~!");
};
好了,再运行一下 npm start
试试。是不是很开心:哎呦,不错呦~!
。
三、总结:
Node
环境下的前端项目开发跟以往全靠在 html
文件中引入 js
文件的方式有许多不同点,这会让我们有些不习惯,但这并不重要,拥抱新技术才是我们程序猿成长、快乐的根本不是吗?