想品客老师的第十一天:模块化开发

模块化概念

模块化开发可以提高代码的可维护性、可读性和复用性,同时降低开发和调试的复杂性,把业务根据功能分开写,解决变量命名的冲突,可以开放部分接口给类(例如调用模块里的一个函数)也更适合团队协作

模块化的开发方式可以提供代码复用率,方便进行代码的管理。通常来说,一个文件就是一个模块,有自己的作用域,只向外暴露特定的变量和函数。目前流行的js模块化规范有CommonJS、AMD、CMD以及ES6的模块系统。

开发一个模块管理工具

在这里我们自己写一个,可以更好的理解模块管理

实现模块的添加、定义、依赖,使用容器管理模块

其他想说的都在代码里了:

   let module = (function () {
            const moduleList = {}//存储模块
            function define(name, modules, action) {
                modules.map((m, i) => {
                    modules[i] = moduleList[m]
                })//map方法的参数,m是模块,i是编号,从容器里拿出来
                moduleList[name] = action.apply(null, modules)//在模块容器里放一个模块,初始化的时候会执行
                //console.log(moduleList)
            }
            return { define }
        })()//一个立即执行函数
        //module.define(name, modules, function (){})是在定义模块,name是模块的名字,modules表示依赖哪个模块,function表示模块的具体动作
        module.define('count', [], function () {//[]表示不依赖别的模块
            return {
                first(arr) {//返回第一个元素的功能
                    return arr[0]
                },
                max(arr, key) {//返回最大元素的功能
                    return arr.sort((a, b) => b[key] - a[key])[0]
                }
            }//return,导出
        })//count模块,对外输出了两个函数
        module.define('lesson', ['count'], function (result) {//['count']是在导入,result是count的结果
            let data = [
                { name: 'js', price: 199 }, { name: 'mysql', price: 78 }
            ]
            console.log(result.max(data, 'price'))//{name: 'js', price: 199}
        })


        //我是一条分割线,下面的是有模块依赖的使用
        module.define('User', [], function () {
            return {
                site: '我是初始值',
                url: '我是初始url'
            }
        })
        module.define('change', ['User'], function (User) {
            User.site = '初始值在change模块被改变了'
        })//模块的改变是全局的
        module.define('show', ['User'], function (User) {
            console.log('我是show模块', User)
        })

模块的基本使用

js的模块部分写在外面的部分,在访问的时候只能访问对外开发的部分,并且表明自己引用的是哪部分:

<script type="module">
    import { title, url, show } from "./hd.js"//访问./hd.js里的tittle、url、show
    show();
  </script>

这是模块,可以在模块内决定谁开放谁不开放

class Lesson {
  data = [];
  init() {
    this.data = [{ name: "js" }, { name: "vue.js" }];
  }
  get() {
    return this.data;
  }
}
let obj = new Lesson();
obj.init();
export { obj };//开放obj

模块延迟解析与严格模式

模块的延迟解析(Deferred Parsing)是 JavaScript 模块(type="module")在浏览器中的一种行为特性。它指的是浏览器在加载模块时,不会立即解析和执行模块代码,而是延迟到文档解析完成后才进行。

模块的延迟解析特性:

延迟执行:当浏览器遇到 <script type="module"> 时,它会异步加载模块文件,但不会立即执行模块代码,模块代码的执行会被延迟到整个 HTML 文档解析完成之后

按顺序执行:模块脚本会按照它们在文档中出现的顺序依次执行,即使模块是异步加载的,类似于<script>里的defer

不会阻塞dom解析:模块脚本不会阻塞 HTML 文档的解析和渲染。

适用于依赖dom的脚本:由于模块代码的执行被延迟到文档解析完成后,模块中可以安全地访问和操作 DOM 元素,而不需要等待 DOMContentLoaded 事件。

  <script type="module">//模块脚本写法,浏览器会将其作为 ES6 模块处理。
    import {} from "./hd.js"//从./hd.js模块导入内容
    console.log(this)//模板脚本为严格模式,this为undefined
  </script>
  <script>//普通脚本写法
    console.log(this)//普通脚本this为window
  </script>
  <body>
    <button>后盾人</button>
  </body>

它确保了模块代码的执行不会阻塞文档的解析和渲染,同时保证了模块可以安全地操作 DOM。这种特性使得模块脚本更适合在现代 Web 开发中使用,尤其是在需要操作 DOM 的场景中。

作用域在模块的体现

每个模块就是一个独立的作用域,不同的模块访问不到彼此的变量

   <script type="module">
        let site = '荷叶饭'
    </script>
    <script type="module">
        console.log(site)
    </script>

两个外部的模块作用域也是不同的,互相直接调用也会报错

但是export出来就可以被访问

模块预解析

模块无论加载多少次,只会在第一次的时候执行

只解析一次是有好处的,可以起到初始化的作用

class lesson {
    data = []
    init() {
        this.data = [{ name: 'js' }, { name: 'mysql' }]
    }
    get() {
        return this.data
    }
}

let obj = new lesson()
obj.init()
export { obj }

模块的具名导出与导入

具名和匿名比,就是有具体的名字

export let site = '后盾人'
export function show() {
    return 'show function'
}
export class User {
    static render() {
        return 'user static render'
    }
}

这是具名的引入和导出

批量导入

一个一个导入:

   import { site, show, User } from "./modules/m7.js";
    console.log(site);
    console.log(show());
    console.log(User.render());

批量导入的格式

    <script type="module">
        import *as api from './0204model.js'
        console.log(api)
    </script>

api里的内容

打印里面的内容:

       import *as api from './0204model.js'
        console.log(api.site)
        console.log(api.show())
        console.log(api.User.render())

导入和导出的别名使用

导入的变量可以起个别名方便使用:

     import { site as othername } from './0204model.js'
        console.log(othername)//后盾人

导出的时候也可以起别名(逆天语法):

let site = '后盾人'
export { site as hd }

导入也可以给导出起过别名的的变量起别名:

//模块导出
let site = '后盾人'
export { site as hd }
//导入
 import { hd as othername } from './0204model.js'
        console.log(othername)//后盾人

default默认导出

一般导出加{}是一次导出多个值,也可以使用默认导出

export default class User {
    static render() {
        return 'user static render'
    }
}
import User from './0204model.js'//默认导出的内容赋值给User
    console.log(User)//所以User是一个类

也可以单独写一个默认导出:

//export default class User {
//    static render() {
//        return 'user static render'
//    }
//}

class User {
    static render() {
        return 'user static render'
    }
}
export {User as default}

默认导出就导出来一个,所以用什么名字导入是随意的:

  import User from './0204model.js'//默认导出的内容赋值给User
    console.log(User)//所以User是一个类
      import sjb from './0204model.js'//换个名字也可以
        console.log(sjb)//User是一个类

这样和具名导出是不一样的,一次只导出来一个哦

混合导入导出

上面讲了默认和具名,混着用就是混合导入导出

  import * as api from "./modules/m11.js";
    console.log(api.default.render());
    console.log(api.site);

后盾人老师更建议具名导出,因为默认导出会随意起名字,具名导出可以给名字指定规范

一般让模块名和具名的名字相关,方便阅读开发

模块的合并导出

一个也业务同时用到很多模块的时候怎么处理?

可以设计一个‘中间站’,这个中间站导入所有要用的模块再导出

import { site,url } from "./0202model.js";
import User,{ web } from "./0204model2.js";
export{site,url User,web}

如果不同模块有重复命名的问题,可以把同一个模块里的数据包在一起,另一个模块的数据包在一起

下面的代码是把两个模块的数据发到中间站合并位两个组,中间站再发回html部分,合并为一个组

//group1
export let web='http://'
export default class User{
    static show(){
        return 'use static method show'
    }
}
//group2
let site='111'
let url='uuu'
export {site,url}
//中间站
import *as group1 from "./0204model.js";
import *as group2 from "./0204model2.js";
export { group1, group2 }
//html
<script type="module">
import *as api from './temp.js'
console.log(api)
</script>

按需加载动态模块

有时候可能需要这堆模块,比如提交表单的模块;有时候需要那堆模块,收集信息的模块

这时候就需要按需加载

使用import函数,import() 是 JavaScript 中的一种动态导入语法,它允许你在运行时异步加载模块。import() 返回一个 Promise,成功时解析为模块对象,失败时返回错误。

<body>
    <button>houdunren</button>
  </body>
  <script type="module">
    //import
    document.querySelector("button").addEventListener("click", () => {
      import("./0204model2.js").then(({ site, url }) => {
        console.log(site, url);
      });
    });
  </script>

点击按钮时,按需加载模块

模块管理工具把es6语法->es5语法

 WEBPACK构建项目的软件安装:安装node.js->安装webpack

webpack与前端模块化开发实践-优快云博客

安装明天再说

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值