美文网首页
模块化的理解

模块化的理解

作者: FConfidence | 来源:发表于2018-09-10 13:16 被阅读47次

    模块化方式

    什么是模块化
    所谓的模块化开发就是封装细节,提供使用接口,彼此之间互不影响,每个模块都是实现某一特定的功能。模块化开发的基础就是函数

    • 函数封装

      • "污染"了全局变量,无法保证不与其他模块发生变量名冲突,而且模块成员之间看不出直接关系。
    • 对象方式

      var module1 = {
           _count : 0,
          m1 : function (){
            //...
          },
          m2 : function (){
            //...
          }
      }
      // 这样的写法会暴露所有模块成员,内部状态可以被外部改写。比如,外部代码可以直接改变内部计数器的值。module1._count = 1;
      
    • IIFE

      var module1 = (function(){
          var _count = 0;
          var m1 = function(){
            //...
          };
          var m2 = function(){
            //...
          };
          return {
            m1 : m1,
            m2 : m2
          };
        })();
      
    • 放大模式

      • 如果一个模块很大,必须分成几个部分,或者一个模块需要继承另一个模块,这时就有必要采用"放大模式"(augmentation)。在原有的基础上扩展更多的方法
      var module1 = (function (mod){
          mod.m3 = function () {
            //...
          };
          return mod;
        })(module1);
      
      // 上面的代码为module1模块添加了一个新方法m3(),然后返回新的module1模块,方便方法连续调用。如何防止module1为null或underfined的情况了?
      
    • 宽放大模式

      • 在浏览器环境中,模块的各个部分通常都是从网上获取的,有时无法知道哪个部分会先加载。如果采用上面的写法,第一个执行的部分有可能加载一个不存在空对象,这时就要采用"宽放大模式"。
      var module1 = (function (mod){
      
              return mod;
        })(window.module1 || {}); // 确保对象不为空
      
      // 与"放大模式"相比,"宽放大模式"就是"立即执行函数"的参数可以是空对象,解决了非空问题。
      
    • 输入全局变量

      • 独立性是模块的重要特点,模块内部最好不与程序的其他部分直接交互。为了在模块内部调用全局变量,必须显式地将其他变量输入模块。
      var module1 = (function ($, YAHOO) {
          //...
        })(jQuery, YAHOO);
      

    COMMONJS 服务器端同步加载

    1. 再来说说 module.exports 和 exports,用法其实是相似的,但是不能对 exports直接赋值,不会有任何效果。
    2. 对于 CommonJS 和 ES6 中的模块化的两者区别是:
      • 前者支持动态导入,也就是 require(${path}/xx.js),后者目前不支持,但是已有提案
      • 前者是同步导入,因为用于服务端,文件都在本地,同步导入即使卡住主线程影响也不大。而后者是异步导入,因为用于浏览器,需要下载文件,如果也采用导入会对渲染有很大影响
      • 前者在导出时都是值拷贝,就算导出的值变了,导入的值也不会改变,所以如果想更新值,必须重新导入一次。但是后者采用实时绑定的方式,导入导出的值都指向同一个内存地址,所以导入值会跟随导出值变化
      • 后者会编译成 require/exports 来执行的

    AMD (Asynchronous Module Definition)

    "异步模块定义"。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。

    require([module], callback);
    

    requirejs的使用

    1. 为什么要使用requirejs

      • 加载的时候,浏览器会停止网页渲染,加载文件越多,网页失去响应的时间就会越长;

      • 由于js文件之间存在依赖关系,因此必须严格保证加载顺序(比如上例的1.js要在2.js的前面)

      • 依赖性最大的模块一定要放到最后加载,当依赖关系很复杂的时候,代码的编写和维护都会变得困难。

      • requirejs 特性

        1. 实现js文件的异步加载,避免网页失去响应;
        2. 管理模块之间的依赖性,便于代码的编写和维护。
    2. requireJs的加载

      <script src="js/require.js" data-main="js/main"></script>
      
      1. data-main属性的作用是,指定网页程序的主模块。
      2. 在上例中,就是js目录下面的main.js,这个文件会第一个被require.js加载。
      3. 由于require.js默认的文件后缀名是js,所以可以把main.js简写成main。
      
    3. 主模块的写法

      主模块",意思是整个网页的入口代码。它有点像C语言的main()函数,所有代码都从这儿开始运行。下面就来看,怎么写main.js。

      require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
          // some code here
              // require.js会先加载jQuery、underscore和backbone,然后再运行回调函数。主模块的代码就写在回调函数中。
        });
      /*
      require()函数接受两个参数。
          第一个参数是一个数组,表示所依赖的模块,上例就是['moduleA', 'moduleB', 'moduleC'],即主模块依赖这三个模块;
          第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用。加载的模块会以参数形式传入该函数,从而在回调函数内部就可以使用这些模块。
      */
      

    相关文章

      网友评论

          本文标题:模块化的理解

          本文链接:https://www.haomeiwen.com/subject/yiksgftx.html