JS模块化,ESM模块规范的 导入、导出、引用、调用详解

这篇具有很好参考价值的文章主要介绍了JS模块化,ESM模块规范的 导入、导出、引用、调用详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

写在前面

在之前的 JS模块化的各种规范 之 CJS、AMD、CMD、UMD、ESM 文章中,介绍了关于JS模块化的各种规范的区别和简单使用。
由于ESM模块规范也是 ECMAScript2015(ES6)中的规范标准,在日常的Web项目开发、小程序开发、APP开发等都是很常用的,所以本文重点将 ESM模块规范中的 导出、导入、导出、引用、调用等,结合日常开发需求做进一步的介绍。

实例代码

这里分别以不同的实例代码,逐步介绍ESM模块规范的导出、 导入、引用、调用等使用方法。

1、模块导出 - export

模块导出 就是将js文件中的 变量、常量、函数、对象、类 等对象 向外导出(暴露)以方便外部的js文件所引用和调用。
在JS的ESM模块规范中,主要通过 export 关键字 来 向外导出想要导出(暴露)的对象。

导出之 - 独立导出

独立导出方式,是直接在要向外导出(暴露)变量、常量、函数、对象、类 等对象的对面加上 export 关键字即可!

export let count = 666;

export const PI = Math.PI;

const random = Math.random();
export { random as default };

export const sum = (n1, n2) => {
    return n1 + n2;
};

export function isOdd(n) {
    return n % 2 === 1 || n % 2 === -1;
};

export class Person {
    constructor(name) {
        this.name = name;
    }
    sayHello() {
        console.log(`Hello! 我是${this.name}`);
    }
};

导出之 - 集中多个导出

集中多个导出方式,一般是在代码的最底部,将要向外导出(暴露)变量、常量、函数、对象、类等对象,通过 export export default 以对象的形式导出!

let count = 666;

const PI = Math.PI;

const sum = (n1, n2) => {
    return n1 + n2;
};

function isOdd(n) {
    return n % 2 === 1 || n % 2 === -1;
};

class Person {
    constructor(name) {
        this.name = name;
    }
    sayHello() {
        console.log(`Hello! 我是${this.name}`);
    }
};

// 集中多个导出
export {
    count, // 注:如果对象中的 键key 和 值value 的命名完全相同 可省去 :random 后面这部分!!
    PI,
    sum,
    isOdd,
    Person
};

导出之 - 默认导出

默认导出方式,是使用 export default 关键字 直接导出,该导出方式只能导出单个内容。

// 可直接向外导出(暴露)变量、常量、函数、对象、类等对象
export default function sayHello(name) {
    console.log(`Hello! 我是${name}`);
};
  • 注意:export default 默认导出 在一个js模块文件中,不能同时存在多个默认导出(也就是说,在一个js模块文件中 export default 能只出现一次!!!)

导出之 - 集中默认导出

集中默认导出方式,是使用 export default 关键字 以对象形式导出,该导出方式可以同时导出多个内容。

const PI = Math.PI

function isOdd(n) {
    return n % 2 === 1 || n % 2 === -1;
};

class Person {
    constructor(name) {
        this.name = name;
    }
    sayHello() {
        console.log(`Hello! 我是${this.name}`);
    }
};

export default {
    count: 666,
    PI,
    sum: (n1, n2) => {
        return n1 + n2;
    },
    isOdd,
    Person,
    sayHello: function (name = '') {
        console.log(`Hello! 我是${name}`);
    },
};

导出之 - 混合导出

混合导出方式,就是 在一个JS模块文件中,既有独立导出、集中导出 又有 默认导出、集中默认导出等形式一起组合导出。

📢下面混合导出的代码内容 以 demo.js 文件命名,为接下来的模块 导入、引用、调用实例做演示用!!

/**
 * demo.js
 */

let count = 666;

// 独立导出 常量
export const PI = Math.PI;

const sum = (n1, n2) => {
    return n1 + n2;
};

// 独立导出 函数
export function isOdd(n) {
    return n % 2 === 1 || n % 2 === -1;
};

// 独立导出 类
export class Person {
    constructor(name = '') {
        this.name = name;
    }
    sayHello() {
        console.log(`Hello! 我是${this.name}`);
    }
};

// 默认导出
export default {
    // 默认导出 变量
    count: count,

    // 默认导出 函数
    sum,

    // 默认导出 类
    Person,

    // 默认导出 字符变量 (可直接创建 并 导出[ 变量、常量、函数、对象、类] 等对象)
    pi: '3.141592653589793',

    // 默认导出 函数 方式1
    is: function (val, type) {
        return toString.call(val) === `[object ${type}]`;
    },

    // 默认导出 函数 方式2
    isArray: (arr = []) => {
        return Object.prototype.toString.call(arr) === '[object Array]' || Array.isArray(arr);
    },
    // 默认导出 函数 方式3
    isObject(val) {
        // 注:在这里还可以通过 this关键字 来调用当前默认导出模块中的 其他导出属性内容
        // 如 this.pi; this.sum(1, 2);
        return val !== null && this.is(val, 'Object') || (typeof val === 'object' && val !== null);
    },
    // 默认导出 类
    AudioTrack: class {
        constructor(trackId = '', trackName = '', trackUrl = 'https://') {
            this.trackId = trackId;
            this.trackName = trackName;
            this.trackUrl = trackUrl;
        };
        start() {
            console.log(`开始播放${this.trackName}`);
        };
        stop() {
            console.log(`停止播放${this.trackName}`);
        };
    }
};

2、模块导入 - import

在JS的ESM模块规范中,
当通过 export 关键字 来 向外导出想要导出(暴露)对象以后,
就可以通 import 关键字 来 导入 对应的(注:要一一对应) 导出内容。

导入之 - 全部导入

全部导入方式,使用 ⁎星号 将模块文件中所有的import 独立导出、export default 默认导出 等导出的内容全部导入进来

import * as all from "./demo.js";
// 注:通过export default 关键 默认导出(暴露)的内容在default属性中,和export独立导出的在同一级上!!
console.log('demo.js模块 所有导出的内容:', all);

导入之 - 默认导入

默认导入方式,只会将导出文件中通过export default 关键字向外 导出(暴露)的内容导入进来。

import def from "./demo.js";
// 注:该导入方式只会 export default 关键字向外 导出(暴露)的内容导入进来!
console.log('demo.js模块 默认导出的内容:', def );

导入之 - 指定导入

指定导入方式,是将导出文件中通过export 关键字向外 导出(暴露)的内容 根据指定变量名(不分顺序)的导入进来。

// 指定将PI, isOdd, Person 导入进来
import { PI, isOdd, Person } from "./demo.js";

导入之 - 混合导入

混合导入方式,就是将导出文件中通过export default 关键字 和 export 关键字 向外 导出(暴露)的内容 根据指定变量名(不分顺序)的导入进来。

// 注:def 接收的就是在导出文件中通过export default 关键字向外导出内容,而在大括号{}中接收到在导出文件中通过export关键字向外导出内容。
// 注:def 这个变量名字是可能自定义的。
import def, { PI, isOdd, Person } from "./demo.js";

导入之 - 改名导入

改名导入,是在导入时的 变量名 和 当前文件中的 变量名 有冲突(相同)时,通过 as 关键字 将导入的变量 新更改一下名字,再导入进来。

// 将原大写的PI 更改为 小写的pi
import def, { PI as pi, isOdd, Person } from "./demo.js";

// 当前文件中的 变量名 有冲突
const PI = '3.141592653589793 ';
console.log(PI, pi);

3、模块导入即导出

模块导入即导出方式,一般主要是用于,为了尽可能的减少 在各个JS模块文件之间出到多次导入问题的。
例如:
在A.js模块文件中,同时需要用到B.js模块文件 和 C.js模块文件。
而B.js模块文件中也要用到C.js模块文件。
此时: 我们可以只需在A.js模块文件中 导入 B.js模块文件,然后B.js模块文件中 导入 C.js模块文件即可。

导入即导出之 - 所有导入导出

所有导入导出,是将模块所有的内容导入 又 全部导出。

  • 这里扮演的B.js模块文件 向A.js模块文件 导出C.js模块文件中的所有导出 。
export * from './demo.js';

导入即导出之 - 默认导入导出

默认导入导出,是将 demo.js模块文件中的 export default 默认模块向外导出。

export  { default } from './demo.js';

导入即导出之 - 默认改名导入导出

将 demo.js模块文件中的 export default 默认模块改名在MyDemo下向外导出。

export  { default as MyDemo } from './demo.js';

导入即导出之 - 指定多个导入导出

指定多个导入导出,是将导出文件中通过export 关键字向外 导出(暴露)的内容 根据指定变量名(不分顺序)的导入和导出

  • 这里扮演的B.js模块文件 向A.js模块文件导出PI, random, isOdd,【在A.js模块文件中,同时需要用到B.js模块文件 和 C.js模块文件】。
export  { PI, random, isOdd } from './demo.js';

导入即导出之 - 混合导入即导出

混合导入即导出,就是将 默认模块 和 指定多个变量一起导出。

// 注:default 是关键字,它装着在导出模块文件中通过export default默认导出的内容。
export { default PI, isOdd, Person } from './demo.js';

// 将 demo.js模块文件中的 export  default 默认模块改名在myDef后向外导出。
export { default as myDef, PI, isOdd, Person } from './demo.js';

4、模块引用与调用

在模块导入以后 引用与调用,就是在模块导入以后 就和 我们平时在一个js文件中写代码一样去引用和调用 变量、常量、函数、对象、类 等对象一样,直接使用即可。

引用与调用之 - 本地资源加载

在vite + vue3 项目开发过程,有时需要在 js 代码中去加载本地图片,由于vite默认不支持 require()方法,所以我们可以使用 import来加载本地资源,而且 在项目构建(打包)后也能正常的显示资源。

  • 注:在下面代码中, 资源前面的…/assets/ 是根据当前这个getLocalFile()函数所在的js文件的相对路径,在vue项目中,一般这个文件是放在src目录下面的utils文件夹里面,而资产文件则一般是放在src目录下面的assets文件夹里面,utils 和 assets是同一级目录的(都在src目录下);

function getLocalFile(url) {
	return new URL(`../assets/${url}`, import.meta.url).href;
};
getLocalFile('img/logo.jpg');

// ts写法的简写
const getLocalFile = (url: string): string => new URL(`../assets/${url}`, import.meta.url).href;
getLocalFile('img/logo.jpg');

引用与调用之 - 异步(按需)加载模块

模块异步加载,在一些业务场景中是非常有用的,例如:聊天室,在用户进入聊天室之前需要先进行登录后才能进入,所以在用户没登录成功以前,WebSocket是不应该连接的,需要等到登录成功以后才连接。文章来源地址https://www.toymoban.com/news/detail-743050.html


function load() {
    import('./demo.js').then((esm) => {
        console.log('esm就是./demo.js模块文件中所有导出的内容:', esm);
        console.log(esm.PI);

        const def = esm.default;
        console.log('esm.default就是./demo.js模块文件中默认导出的内容:', def);
        def.sum(100, 200);
    });

    import('./demo.js').then(({ PI, isOdd, Person }) => {
        console.log('也可以直接解构./demo.js模块文件分别独立导出的内容:', PI, isOdd, Person);
        isOdd(666);
        const p = new Person('沐枫');
        p.sayHello();
    });
};

// 在用户点击以后再去加载 想要引用和调用的模块。
btn.onclick = function () {
    load();
};


// 注:如果是在html文件中直接使用时,需要在script标签中加上type="module"属性,并且要在http服务器环境中打开才能正常使用哦!!
<script type="module">
	import('./demo.js').then((esm) => {
 		...
 	});
</script>

到了这里,关于JS模块化,ESM模块规范的 导入、导出、引用、调用详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 模块化规范

    常用模块化有两种规范,commonJS和ES6 我们常遇到的使用场景是,在commonJS的模块里需要引入ES6规范的模块。这时就需要把ES6模块转译为commonJS规范的模块,否则报错 转义工具有: Babel:Babel 是一个流行的 JavaScript 编译器,它可以将 ES6 模块转译为 CommonJS 模块。你可以使用 Bab

    2024年02月15日
    浏览(34)
  • PCB模块化设计05——晶体晶振PCB布局布线设计规范

    1、布局整体紧凑,一般放置在主控的同一侧,靠近主控IC。 2、布局是尽量使电容分支要短(目的:减小寄生电容,) 3、晶振电路一般采用π型滤波形式,放置在晶振的前面。 1)走线采取类差分走线; 2)晶体走线需加粗处理:8-12mil,晶振按照普通单端阻抗线走线即可;

    2024年02月12日
    浏览(31)
  • TS编译器选项——指定编译ES版本和模块化使用规范

    compilerOptions是TS的编译器选项,主要在tsconfig.json文件中用于对ts编译为js文件时进行配置 \\\"compilerOptions\\\" : { 配置项 } 版本可以为如下版本:\\\'es3\\\', \\\'es5\\\', \\\'es6\\\', \\\'es2015\\\', \\\'es2016\\\', \\\'es2017\\\', \\\'es2018\\\', \\\'es2019\\\', \\\'es2020\\\', \\\'es2021\\\', \\\'es2022\\\', \\\'esnext\\\'. 版本可以为如下版本:\\\'none\\\', \\\'commonjs\\\', \\\'amd\\\', \\\'system\\\', \\\'u

    2024年02月04日
    浏览(37)
  • PCB模块化设计09——RJ45-以太网口PCB布局布线设计规范

    以太网(Ethernet)是一种计算机局域网组网技术,该技术基于IEEE制定的IEEE 802.3标准,它规定了包括物理层的连线、电信号和介质访问层协议的内容。 以太网是当前应用最普遍的局域网技术。Ethernet的接口是实质是MAC通过MII总线控制PHY的过程。 以太网接口电路主要由MAC控制器

    2024年02月10日
    浏览(41)
  • JS模块化系统

    随着 JavaScript 开发变得越来越广泛,命名空间和依赖关系变得越来越难以处理。人们已经开发出不同的解决方案以模块系统的形式来解决这个问题。 CommonJS 是一种同步加载模块的规范,主要用于服务器端的 Node.js 环境。 top:CommonJS 加载的是一个对象(即 module.exports 属性),

    2024年02月19日
    浏览(32)
  • js模块化开发

    ◼ 到底什么是模块化、模块化开发呢?  事实上模块化开发最终的目的是将程序划分成一个个小的结构;  这个结构中编写属于自己的逻辑代码,有自己的作用域,定义变量名词时不会影响到其他的结构;  这个结构可以将自己希望暴露的变量、函数、对象等导出给其结

    2024年02月13日
    浏览(37)
  • js 模块化

    模块化主要是用来抽离公共代码,隔离作用域,避免变量冲突等。 模块化的整个发展历史如下: IIFE :使用自执行函数来编写模块化,特点:在一个单独的函数作用域中执行代码,避免代码冲突。 AMD :使用 require 来编写模块化,特点:依赖必须提前声明好。 CMD :使用 seaJS

    2024年02月14日
    浏览(30)
  • Node.js模块化

    说明:将复杂的程序文件,拆分多个文件的过程。模块的内部数据是私有的,不过模块可以暴露内部数据供其他模块使用。 说明:编码时是按照模块一个一个编码的,整个项目就是一个模块化的项目。 3.模块化的优势 说明: 提高代码的复用性:模块化可以将代码分解为可重

    2024年02月12日
    浏览(46)
  • Node.js--模块化

    1.1 什么是模块化与模块 将一个复杂的程序文件依据一定规则(规范)拆分成多个文件的过程称之为 模块化 其中拆分出的 每个文件就是一个模块 ,模块的内部数据都是私有的,不过模块可以暴露内部数据以便其他模块使用 1.2 什么是模块化项目 编码时是按照模块一个一个编码

    2024年02月16日
    浏览(37)
  • 【node.js】04-模块化

    目录 一、什么是模块化 二、node.js中的模块化 1. node.js中模块的分类 2. 加载模块 3. node.js 中的模块作用域 4. 向外共享模块作用域中的成员 4.1 module对象  4.2 module.exports 对象 4.3 exports对象 5. node.js 中的模块化规范          模块化是指解决一个复杂问题时,自顶向下逐层

    2024年02月15日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包