有个前端项目,需要用到配置文件。这个配置文件实在是太大了,就想拆成多个小的,然后一一引入,组合成一个完整的配置文件。

如果是vue代码,这种情况根本是手到擒来,不费吹灰之力,而该前端项目是个普通的js程序。但其实,在编写VUE代码过程中,我们所熟知的import,export,并不是VUE的语法,而是js es6(?)的语法。所以,虽然不是VUE项目,现在一般的浏览器都能支持js代码中使用import和export。

思路是这样的:

1)将配置文件拆成一个主配置文件,以及多个小的js文件
2)每个小js文件里将内容通过export输出
3)在主配置文件中import这些小js文件
4)在html页面中引入该主配置文件,引入时,​​​<script>​​ 标记里需要加上 type=“module” 属性。

结果出来的问题就是,引入主配置文件后,里面的内容外部好像获取不到,说是没有定义,not defined。

究其原因,主要集中在2点:

1)通过<script type=“module” src="js模块文件’ />引入的js模块文件,里面的变量不是全局性的,而是模块内部的
2)上面的加载语句,加载出来的内容,只有等到页面全部加载完毕后才能访问,一般放在window.onload事件里处理

下面是详细介绍。
1、小配置文件

//hjzl.js
export default [
{
pid: "hjzl",
id: "hjzl-water",
name: "花果山环境质量",
type: "group",
open: true,
},
{
pid: "hjzl-water",
id: "hjzl-water-2022",
name: "2022年东海海水质量",
type: "group",
open: false,
},
{
pid: "hjzl-water",
id: "hjzl-water-2022",
name: "2021年东海海水质量",
type: "group",
open: false,
},
];

第一种引用方式

2、主配置文件
//config.js

import baseMaps from "./_baseMaps.js";
import baseLayers from "./_baseLayers.js";
import hjzl from "./_hjzl.js";
import hjjc from "./_hjjc.js";
import hjjg from "./_hjjg.js";
import hjyj from "./_hjyj.js";
import widgets from "./_widgets.js";

//注意是window.config
window.config = {
title: "花果山水帘洞新时代幺百零八五规划",
plans: [...baseLayers, ...hjzl, ...hjjc, ...hjjg, ...hjyj],
};

3、html

<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8" />
<title>齐天大圣府办公室</title>

<script type="module" src="./config.js">
</script>

<script>
if (window.addEventListener) {
// W3C standard
window.addEventListener("load", _init, false); // NB **not** 'onload'
} else if (window.attachEvent) {
// Microsoft
window.attachEvent("onload", _init);
}
function _init() {
console.log(config);
}
</script>
</head>

第二种引用方式

2、主配置文件
//config.js

import baseMaps from "./_baseMaps.js";
import baseLayers from "./_baseLayers.js";
import hjzl from "./_hjzl.js";
import hjjc from "./_hjjc.js";
import hjjg from "./_hjjg.js";
import hjyj from "./_hjyj.js";
import widgets from "./_widgets.js";

//export ...
export default {
title: "花果山水帘洞新时代幺百零八五规划",
plans: [...baseLayers, ...hjzl, ...hjjc, ...hjjg, ...hjyj],
};

3、html

<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8" />
<title>齐天大圣府办公室</title>

<script type="module">
import config from "./config.js";
window.config = config;//这句绝对不是多余
</script>

<script>
if (window.addEventListener) {
// W3C standard
window.addEventListener("load", _init, false); // NB **not** 'onload'
} else if (window.attachEvent) {
// Microsoft
window.attachEvent("onload", _init);
}
function _init() {
console.log(config);
}
</script>
</head>

有关js文件加载顺序

js文件模块化引用问题(JavaScript modules)_export


我猜这幅图的意思是,

1)通常js文件下载时,是下载完js并执行,html的解析会受到中断和阻塞;

2)如果加上属性defer,那么下载js和解析html会并行,并且直到所有html加载完毕才执行该js

3)如果加上属性async,下载js和解析html会并行,然后中断html,执行js

4)如果type=“module”,那么就跟加defer属性一样。当然,module文件里有可能会引用其他module,它们也是并行下载的

5)如果type="module"同时async,参考3

所以,type="module"的情况下,js会在html加载完毕才执行,因此,module里面的内容只有放在window.onload里才能处理。

参考文章:

​https://v8.dev/features/modules#defer​

​https://javascript.info/modules-intro​