关键词搜索

源码搜索 ×
×

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

发布2022-12-03浏览2036次

详情内容

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

如果是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: "西牛贺洲环境质量",
    type: "group",
    open: false,
  },
  {
    pid: "hjzl-water",
    id: "hjzl-water-2022",
    name: "东海龙宫环境质量",
    type: "group",
    open: false,
  },  
];  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

第一种引用方式

将配置内容直接赋给变量config:

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
//将配置内容直接赋给变量config
window.config = {
  title: "花果山水帘洞新时代幺百零八五规划",
  plans: [...baseLayers, ...hjzl, ...hjjc, ...hjjg, ...hjyj],
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

在页面加载完毕后读取变量config的值:

3、html

<!DOCTYPE html>
<html lang="zh-cn">
  <head>
    <meta charset="utf-8" />
    <title>齐天大圣府办公室</title>
    
    <script type="module" src="./config.js">
    </script>
    
    <script>
	    //在页面加载完毕后读取变量config的值
	    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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

第二种引用方式

将配置内容export:

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],
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

用全局变量config接收导出的配置内容,同样在页面加载完毕后读取变量config的值:
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;//这句绝对不是多余,用全局变量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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

有关js文件加载顺序

在这里插入图片描述
我猜这幅图的意思是,
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

相关技术文章

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载