js模块化(自己瞎玩记录而已)

253 阅读3分钟

1.js模块化演变过程

     1.通过立即执行函数达到隐藏私有变量、暴露公共方法
     2.通过require.js sea.js这一类js模块加载框架
     3.通过ES6 import实现js模块化

2.代码演示

     1.通过立即执行函数达到隐藏私有变量、暴露公共方法

    1. 方案1:
    (function(exports){
        function add(){
        }
        var flag = true;
        var x = 10;
        
        //导出(导出的就相当于全局对象的属性、方法,支持任意一个js模块引用其导出方法、属性)
        //其实就是通过window,将方法属性添加到其上面
        exports.add = add;
        exports.flag = flag;
    })(window)
    2.方案2    
    var module = (function(){
         function add(){        }
        var flag = true;
        var x = 10;        //导出
        return {
          add:add,
          flag:flag
        }
    })()
    // 这两种方案其实都可,但是第一种方案是将对外暴露的方法挂载到window上,说白了还是全局变量。
    第二种方案最多只会暴露一个全局变量,建议第2种。

        2.sea.js 使用

     // sea.js的使用(sea.js会将一个js文件当做一个模块来看,类似的node里的require、exports,sea.js的
        api和node语法很类似,通过require引入,exports导出)
     // 语法:
     // *****定义一个模块******
     // *id:模块id,通常就是当前写的js文件的路径(官方建议id不写)
     // *[]:依赖文件:就是使用这个js之前需要提前引入那些文件(官方建议不写)
     // *callback:第三个参数为回调函数,有三个参数,其中module是整个模块的信息,包括前面所说
        的模块id,模块依赖,可通过console.log(module)查看模块信息
        // 正常写法
        define(id,[],function(require,exports,module){
            
        }) 
        // 推荐写法
        define(function(require,exports,module){
            // 引入a模块
            var a= require('a');
            // 引入b模块
            var b = require('b');
            // 使用a,b模块导出的方法
            a.run();b.sleep();    
            // 定义自己的方法、变量
            var num = 10;
            function eat(){
            }
            // 导出自己的方法、变量
            // 方法1(问什么不能用exports指向对象呢,下面会说明)
            exports.num = num;
            exports.eat = eat;   
            // 方法2
            module.exports = {
                  num : num,
                  eat : eat
            } 
            // 方法3
            return {
                 num : num, 
                 eat : eat
            }
        })
    
        // *****页面内使用sea.js******
        直接<script src="js/sea.js"></script>即可
        // 引入口文件
        <script>
            // 一般一个html的入口文件只有一个
            seajs.use('init.js') 或  seajs.use('init.js',function(){})
            // 如果一个html入口文件有多个
            seajs.use(['init.js','x.js']) 或 seajs.use(['init.js','x.js'],function(){})
        </script>

        // ******sea.js的配置*******
        // 注:只会配置常见项,其他的查看api文档
        seajs.config({
            // base是基础目录,所有的文件都是基于base来查找的,base默认目录是sea.js存在的目录
            // 但是建议不设置(除非你的sea.js放置目录很好,否则麻烦的一匹)
            // base:''
            
            // 设置别名
            alias:{
                 'jquery':''       
            }
            
        })
    
        // 说明一下匹配规则,以及建议常见的使用方案
           * 在seajs配置中,如果别名的设置 以 相对路径设置的,则其的匹配规则是: "以当前页面use使用的目录为
             基准目录,别名目录就以它为基准就行寻找,会导致路径复杂度提高"
           * 如果别名设置是以 'app/jquery'这种目录的,则寻找目录的基准目录为base目录
            常见使用方案:
                1.sea.js源文件放在一个好的位置,什么是好的位置,答案:js文件下的子文件(sea所在目录为js目录)
                2.use () :使用相对路径,不用别名(记住,不为use文件设置别名),规则是:当前html引入该use文件的路径
                3.require():当使用相对路径时,是相对于当前js文件的,如果是require('app')的,则会寻找config的别名配置
       
             总之一句话,sea的位置放的好,其他就都不是问题了。


       常见问题:
            1.为什么不能exports = {}这种格式导出?  
                exports指向了module.exports;真正导出是通过module.exports导出的,exports仅仅是                 module.exports的映射,当exports指向了新的对象,与module.exports的联系便断了。(和node一样)            2. sea中使用jq,报错?
                 jq用一层包裹;
                 define(function(){
                     jq源码
                     return $.noConflict();
                 })
  

           3. ES6语法

    // b.js      
       import {a} from './a.js'
    // a.js
        const a = 10;
        export {a}