js模組化(自己瞎玩記錄而已)

Tra發表於2017-11-29

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} 
複製程式碼


相關文章