简单谈一谈前端模块化

1.什么是模块

  • 将一个复杂的程序依据一定的规则(规范)封装成几个块(文件), 并进行组合在一起。
  • 块的内部数据与实现是私有的, 只是向外部暴露一些接口(方法)与外部其它模块通信。

2.前端模块化进程

  • 函数形式
  • 命名空间,简单对象封装
let myModule = {
  data: 'www.baidu.com',
  foo() {
    console.log(`foo() ${this.data}`)
  },
  bar() {
    console.log(`bar() ${this.data}`)
  }
}
myModule.data = 'other data' //能直接修改模块内部的数据
myModule.foo() // foo() other data
  • 立即执行函数
    将数据和行为封装到一个函数内部, 通过给window添加属性来向外暴露接口
  • 立即执行函数模式增强,引入依赖。如下代码
// module.js文件
(function(window, $) {
  let data = 'www.baidu.com'
  //操作数据的函数
  function foo() {
    //用于暴露有函数
    console.log(`foo() ${data}`)
    $('body').css('background', 'red')
  }
  function bar() {
    //用于暴露有函数
    console.log(`bar() ${data}`)
    otherFun() //内部调用
  }
  function otherFun() {
    //内部私有的函数
    console.log('otherFun()')
  }
  //暴露行为
  window.myModule = { foo, bar }
})(window, jQuery)
 // index.html文件
  <!-- 引入的js必须有一定顺序 -->
  <script type="text/javascript" src="jquery-1.10.1.js"></script>
  <script type="text/javascript" src="module.js"></script>
  <script type="text/javascript">
    myModule.foo()
  </script>

3.模块化的好处

  • 避免命名冲突(减少命名空间污染)
  • 更好的分离, 按需加载
  • 更高复用性
  • 高可维护性

4.模块化规范

  • CommonJS

    • 概述:
      1.据CommonJs规范规定每一个Js文件都可以看作一个模块,其内部定义的变量是属于这个模块的,不会对外暴露,也就是说不会污染全局变量。该规范最初用在服务器端的node环境中。
      2.CommonJS采用同步加载不同模块文件,适用于服务器端的。因为模块文件都存放在服务器的各个硬盘上,读取加载时间快,适合服务器端,不适应浏览器
      3.浏览器不兼容CommonJs,原因是浏览器缺少moduleexportsrequireglobal四个环境变量。如要使用需要工具转换。在浏览器中运行的话,先使用browserify或者webpack工具打包编译。
    • 模块加载机制
      CommonJS模块的加载机制是,输入的是被输出的值的拷贝。也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。不是动态加载的。
    • 语法:
      1.暴露接口方式
      module.exports = value;
      exports.XXX = value;
      (上述两种方式,exports是一个对象,被暴露出去,供其他文件使用。第一种方式:exports被赋予新值暴露。第二种,是在对象上挂载属性,然后暴露出去)
      在 Node.js 模块里,真正控制模块导出的是 module.exports,exports 只是 module.exports 决定导出一个对象时的一个快捷方式,假如 module.exports 导出其它类型的数据,比如字符串、数值、函数等等,则 exports 的存在没有意义
      2.引入模块
      require('XXX');如果是第三方模块,xxx为模块名;如果是自定义模块,xxx为模块文件相对路径。
  • AMD(异步模块定义,Asynchronous Module Definition),适用于浏览器环境

    • 是什么:

      1.AMD规范则是异步加载模块,允许指定回调函数。等模块异步加载完成后即可调用回调函数。
      2.AMD得意的产出就是require.jsrequire官网
      3.AMD的核心思想就是通过define来定义一个模块,然后使用require来加载一个模块。
      4.AMD规范的使用依赖于require.js 。

    • 怎么用
      AMD设计出一个简洁的写模块API:
      define(id?, dependencies?, factory);
      id: 模块标识,可以省略。一般用于库的暴露。如:jquery
      dependencies: 所依赖的模块,可以省略。
      factory: 模块的实现,或者一个JavaScript对象。

下面一个小例子:
目录结构
在这里插入图片描述
index.html

	<!-- 引入require.js文件   并指定js主文件入口 -->
    <!-- (实际上除了require.js,其它文件模块都不再使用script标签引入,可以在demo.js中注明模块路径) -->
    <script src="./js/require.js" data-main="./demo.js"></script>

module1.js

var counter = 0;

function computeCounter () {
   counter++;
   console.log(counter);
   console.log('m1-amd');
}

define(function() {
    'use strict';
    return {counter, computeCounter}; // 暴露该模块
});

module2.js

define(['m1', 'jquery'], function(m1, $) {
    'use strict';
    function getM2Name() {
        m1.computeCounter();
        console.log(m1.counter);
        console.log('m2-amd')
        console.log('$==', $);
    }
    return getM2Name;// 暴露该模块
});

demo.js

(function () {
    require.config({
        baseUrl: './',
        paths: {
            // 模块标识名:路径(路径的出发点在根目录下面哦!!!module1后面不能有.js)
            m1: 'module/module1',  // m1,模块名。m2模块依赖于m1模块
            m2: 'module/module2',
            /**
             * m2模块依赖于第三方模块, 
             *注意“jquery”是固定的,不能写“jQuery”或其它。这里只能写jquery(v1.7以上支持AMD)
             */
            jquery: 'js/jquery'
        }
    })
    require(['m2'], function (m2) {
        console.log(m2);
        m2();
    })
})()
  • CMD规范(Common Module Definition,通用模块定义)。SeaJS就是遵循的这个规范。

    • 是什么?
      CMD规范专门用于浏览器端,模块的加载是异步的,模块使用时才会加载执行。

    • 怎么用?
      CMD的核心思想就是通过define来定义一个模块,然后使用require来加载一个模块。

index.html

	<script src="./js/sea.js"></script>
    <script>
        seajs.use('./demo.js');
    </script>

module1.js

define(function (require, exports, module) {
    var data = 'm1';
    function showM1() {
        return 'module1 show() ' + data;
    }
    exports.showM1 = showM1;
})

module3.js

define(function (require, exports, module) {
    var data = 'm3';
   
    function showM3() {
        console.log('module3 show() ' + data);
    }
    
    exports.showM3 = showM3;
})

module2.js

define(function (require, exports, module) {
    var data = 'm2';

    // 异步加载模块
    require.async('./module1', function (m1) {
        console.log('async====', m1.showM1());
    })

    var m3 = require('./module3');
    m3.showM3();

    function showM2() {
        console.log('module2 show() ' + data);
    }
    
    exports.showM2 = showM2;
})

demo.js

define(function (require, exports, module) {
    var demo = require('./module/module2');
    demo.showM2();
})
  • es6的import
    由于ES6目前无法在浏览器中执行,所以,我们只能通过babel将不被支持的import编译为当前受到广泛支持的 require
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值