乐趣区

关于前端学习:Javascript模块化开发

  • 理解模块化开发

    • 模块化开发是指将一类办法封装在一个 JS 文件 中,每一个不同的性能类的 JS 文件 就是一个模块,而后通过引入不同性能的文件相互配合,实现目标成果
    • 引入多个文件呈现的问题

      1. 文件引入程序,被依赖文件必须在应用被依赖文件内办法的文件后面
      2. 当多个 JS 文件时,产生文件依赖关系不清晰问题
      3. JS 文件外部全局变量净化
  • 模块化开发发展史

  • 没有模块化开发阶段

    1. 依照依赖程序进行进入 JS 文件,最初引入整合文件
    2. 前期无奈进行保护代码,依赖关系不清晰
    3. 全局变量净化,模块文件中的全局变量能够在其余模块或整合文件中间接进行应用,其余文件也无奈定义雷同的变量名
    // 模块文件 a
    <script src="a.js"></script>
    
    // 模块文件 b
    // 文件外部可能应用了 a 文件外部办法,所以须要在 a 文件前面引入
    <script src="b.js"></script>
    
    // 性能整合文件 main
    // 文件是整合文件,应用了 a b 文件内的办法,所以 a b 须要引入在 main 文件后面
    <script src="main.js"></script>
    
    // a.js
    var num = 100;
    function af1(){console.log('a 文件内的 af1 办法')
    }
    function af2(){console.log('a 文件内的 af2 办法')
    }
    
    // b.js
    function bf1(){af2();
        console.log('应用了 a 文件内的 af2 办法')
    }
    function bf2(){console.log('a 文件内的 bf2 办法')
    }
    
    // main.js
    console.log(num) // num 是一个全局变量,所以在 main 文件内能够应用
    af1();
    bf1();
  • IIFE 伪模块化开发阶段(非官方)
    原理:在 JS 文件中书写一个自执行函数,而后将办法写在自执行函数体内,但办法是自执行函数内的局部变量,外界无奈应用,所以须要将外界须要的办法挂载在全局上

    解决的问题:

    1. 通过自执行函数的参数可晓得依赖了哪些模块
    2. 在自执行函数中定义的变量属于局部变量,没有全局变量净化问题

    产生的问题:

    1. 文件引入程序不能动
    2. 尽管晓得依赖了哪些模块,然而不晓得模块是哪个文件的
    // 模块文件 a
    <script src="a.js"></script>
    
    // 模块文件 b
    // 文件外部可能应用了 a 文件外部办法,所以须要在 a 文件前面引入
    <script src="b.js"></script>
    
    // main 文件是整合文件,应用了 a b 文件内的办法,所以 a b 须要引入在 main 文件后面
    <script src="main.js"></script>
    
    
    // 模块文件 a.js
    (function(){
        // 自执行函数执行完结后,变量主动销毁
        var num = 100;
        function af1(){console.log('a 文件内的 af1 办法')
        }
        function af2(){console.log('a 文件内的 af2 办法')
        }
    
        // 将变量和办法挂载在全局上,其余文件可进行应用
        window.madA={
          af1,
          af2,
          num
        }
    })()
    
    // 模块文件 b.js
    (function(madA){
    // 这里的参数接管的是自执行函数参过去的参数
        function bf1(){madA.af2();
            console.log('应用了 a 文件内的 af2 办法')
        }
        function bf2(){console.log('a 文件内的 bf2 办法')
        }
        // 将其余文件须要用到的办法挂在在全局上
        window.madB={
            bf1,
            bf2
        }
    // 传入其余模块文件挂载在全局上的对象名,在函数内进行应用外部变量和办法
    })(madA)
    
    // 模块文件 main.js
    (function(madA,madA){console.log(madA.num) // num 是其余文件挂载在全局上的变量,所以在 main 文件内能够应用
        madA.af1();
        madB.bf1();})(madA,madB)
  • commonJS 模块化开发规范
    CommmonJS 用于 node 端模块化开发(只能用于后端)
    模块化开发标准:

    1. 通过 module.exports 或 exports 来裸露模块
    2. 通过 require 来加载模块

    CommmonJS 的特点:

    1. 同步加载,个别用于 node 端
    2. 一次加载,屡次应用。对同一个模块而言,只会运行一次,屡次应用时会从缓存中获取
    3. 模块加载的程序,依照它呈现的程序
    4. 代码都运行在模块作用域,不会造成全局净化
    //a.js 文件
    var math = {add:function(a,b){return a+b;}
    }
    // module 是代表以后模块,通常通过 module.exports 来裸露模块
    module.exports = math    
    
    //b.js
    // 引入依赖模块
    var math = require('./a.js')// 模块依赖, 通过 require 导入模块
    console.log(math.add(1,2))        
  • AMD 模块化规范(非官方)阶段 ——前置依赖
    由社区发动,没有关键字,并且须要引入第三方文件require.js 应用
    AMD 模块化标准:

    1. 通过 define() 办法定义模块
    2. 通过 require() 办法加载模块
    3. 通过define(['依赖文件地址'···],function(接管依赖文件返回值){}),在模块文件中导入另一个模块文件

    解决的问题:

    1. 文件依赖清晰
    2. 解决全局变量净化问题

    产生的问题:
    前置依赖:文件会在关上页面时加载,首屏加载工夫长,前期晦涩

    // 引入第三方文件
    <script src="require.js"></script>
    
    // 定义一个模块文件
    define(function() {
        var helloInLang = {
          en: 'Hello world!',
          es: '¡Hola mundo!',
          ru: 'Привет мир!'
        };
        // 裸露内容
        return {sayHello: function (lang) {return helloInLang[lang];
            }
        };
    });
    // 引入一个模块
    define(['./lib/greeting'], function(greeting) {
        // 这个形参接管的就是模块返回的办法或内容
        var phrase = greeting.sayHello('en');
    });
    
    // 在整合文件中应用其余模块文件中的变量和办法
    require(['./modules/module1'], function (module1) {module1.sayHello('hello')
    })
  • CMD 通用模块化规范(非官方)——即时依赖
    在社区中,由淘宝“玉伯”开发的 CMD 模块化规范,依赖第三方文件应用
    定义模块:define(function(require, exports, module){})

    1. require()参数用于导入其余文件
    2. exports参数用于将文件导出内容

    解决的问题:解决前置依赖问题,加载时按需加载,也提供了依赖前置的接口

    存在的问题:即时依赖,首屏加载快,操作不够晦涩

    // 引入第三方文件
    <script src="./js/sea.js"></script>
    
    // 定义一个模块文件
    define(function(require, exports, module) {
        // 定义方法
        function fn(){console.log("CMD")
        }
    
        // 在模块文件中导入其余模块
        var mod_A = require('依赖文件地址');
    
        // 导出内容
        module.exports = {fn}
    })
    
    // 整合文件
    define(function(require, exports, module) {seajs.use(['依赖文件地址'], function(modA){调用办法等})
    });
  • ES6(ES2015)模块化规范
    ES6 语法中自带一个模块化规范,提供了关键字,须要在 <script> 标签增加 type=“module”属性,并且只有在服务器上关上才无效
    导出语法:

    1. export default 导出内容
    2. export var 变量名 = 值

    导入语法:

    1. import 变量 from '模块文件地址'
    2. import {接管变量} from‘模块文件地址’
    3. 解决前置依赖问题语法:import('模块文件地址').then(function(形参){})

    解决的问题:不须要依赖第三方文件,每个文件都能够是模块文件,或整合文件

    存在的问题:须要兼容解决

    // 定义一个模块
    export default {
        // 以对象或者数组到处
        function fn (lang) {return helloInLang[lang];
        }
    };
    // 引入一个模块
    import fn from "模块文件";
退出移动版