加载中...
  • js 模块化 导入导出

    模块就是把多个功能分隔成独立的文件,一个模块负责一部分功能,减低代码耦合度
    模块可以给不同的文件划分独立作用域,多个文件中重名的变量不会相互影响
    模块可以开放部分功能给外部

    模块的基本使用

    在 js 中使用 export 导出想要导出的内容

    导出方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    let title = "title";
    let url = "url";

    function show() {
    console.log("show");
    }
    // 导出
    export { title, url, show };

    导入方法

    1
    2
    3
    4
    5
    6
    // 通过import引入
    import { title, url, show } from "./js/2.js";
    console.log(title); // title
    console.log(url); // url
    show(); // show

    模块延迟解析和严格模式

    在代码中使用导入时要在 script 标签上声明 type = “module”, 表示延迟解析,等待所有依赖加载完毕后再往下执行代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <!-- 
    不添加 type="module" 会打印 null
    程序自上而下运行时先打印不会去找button
    但是module模块默认等待所有模块加载完成后再去执行代码,因为模块中会有各种依赖关系
    所以module也是延迟解析
    -->
    <script type="module">
    console.log(document.querySelector("button"));
    import { stit } from "./js/3.js";
    console.log(stit);
    </script>

    <body>
    <button>按钮</button>
    </body>

    作用域在模块中的体现

    每个模块都有自己独立的作用域,自己模块中获取不到其他模块作用域的数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <script>
    // 非模块定义在其他模块可以使用
    let url = "定义外部变量";
    </script>

    <script type="module">
    let title = "标题";
    console.log(title); // 标题
    console.log(url); // 定义外部变量
    </script>

    <script type="module">
    // 每个模块都有自己的作用域,其他模块拿不到其他模块定义的变量
    // console.log(title); title is not defined
    console.log(url); // 定义外部变量
    </script>

    预解析的重要性

    通过预解析正确处理多个 js 之间的相互引用关系,防止未引入先使用导致错误

    在页面中导入两个 js 模块

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <script type="module">
    import { lesobj } from "./js/5.js";
    console.log(lesobj.get());
    // 0: {name: "js", price: 999}
    // 1: {name: "vue", price: 56}

    // 5_1引入5.js
    import { count } from "./js/5_1.js";
    console.log(count); // 2
    </script>

    js 导出 lesobj

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    class lessos {
    data = [];
    init() {
    this.data = [
    {
    name: "js",
    price: 999,
    },
    {
    name: "vue",
    price: 56,
    },
    ];
    }
    get() {
    return this.data;
    }
    }
    let lesobj = new lessos();
    lesobj.init();
    export { lesobj };

    js 使用 5.js 导出的 lesobj

    1
    2
    3
    4
    5
    import { lesobj } from "./5.js";
    let count = lesobj.get().length;

    export { count };

    模块的具名导出和导入

    根据具体的名字导入叫做具名导入,导出具体的名字称为具名导出。

    1
    2
    3
    4
    5
    6
    <script type="module">
    // 根据具体的名字导入叫做具名导入
    import { title, url, user, show } from "./js/6.js";
    console.log(title, url, user.data, show());
    </script>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    let title = "标题";
    let url = "路径";
    class User {
    data = "user.data";
    }
    let user = new User();

    function show() {
    return "show";
    }
    // 有具体的名字导出叫做具名导出
    export { title, url, user, show };

    批量导入

    使用 * as 别名可以批量导入,但是打包时会认为我们要用到这个模块里面的所有内容,
    导致打包文件的体积过大,建议使用具名导入,打包是只会打包我们用到的一些文件

    1
    2
    3
    4
    5
    6
    // 批量导入
    import * as api from "./js/6.js";
    console.log(api);
    // 具名导入(推荐)
    import { title } from "./js/6.js";

    使用别名导出和导入

    使用别名导入后原来的名字便无法使用

    1
    2
    3
    4
    5
    6
    // 使用 as 别名
    import { title as t } from "./js/6.js";
    console.log(t);
    // 使用别后原来的名字不可用
    // console.log(title); title is not defined

    default 默认导出

    使用 default 默认导出是不用 {} 来接收,{} 表示导入多个

    默认导出多个

    1
    2
    3
    4
    export default {
    name: "李四",
    age: "18",
    };

    默认导出后,导入使定义一个变量接收导出的数据

    1
    2
    3
    import api from "./js/9.js";
    console.log(api); // {name: "李四", age: "18"}

    混合导入导出的使用

    默认导出和单个导出可以同时使用
    导出方式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 混合导出
    export default {
    name: "李四",
    age: "18",
    };

    function show() {
    console.log("单个导出");
    }
    export { show };

    导入方式

    1
    2
    3
    4
    5
    // 混合导入
    import api, { show } from "./js/10.js";
    console.log(api); // {name: "李四", age: "18"}
    show(); // 单个导出

    模块的合并导出

    合并导出概念:通过一个模块引入其他多个模块,导入时只导入一个总的模块
    合并导出方式

    1
    2
    3
    4
    5
    6
    import * as m121 from "./12.1.js";
    import * as m122 from "./12.2.js";

    // 通过index文件批量导出
    export { m121, m122 };

    导入方式

    1
    2
    3
    4
    5
    6
    import * as api from "./js/12.index.js";
    console.log(api);
    console.log(api.m121.title);
    // 使用默认导出的类里面的静态方法
    console.log(api.m122.default.show());

    按需动态加载模块

    通过请求的方式加载某个模块

    1
    <button>动态加载</button>
    1
    2
    3
    4
    5
    6
    7
    document.querySelector("button").addEventListener("click", () => {
    // import()函数返回的是一个promise函数
    import("./js/6.js").then(({ title, url }) => {
    console.log(title, url);
    });
    });

    上一篇:
    Symbol 类型 介绍
    下一篇:
    promise详解
    本文目录
    本文目录