自制 require 函數:讓瀏覽器輕鬆實現 js 文件按需加載

唉?這種文章你也點進來看,你不知道有 LABjs、RequireJS、SeaJS... 這些庫嗎?html

反正我是沒用過這些庫,什麼 AMD 、CMD 哪來那麼多術語... 前端的庫太多了,要看各類亂七八糟的文檔,看文檔就想睡覺,就像學一門新語言同樣,好煩啊,還不如本身寫一個庫呢。前端

劇透一下,實現這個功能只須要20行代碼。瀏覽器

好了,要怎麼本身寫一個按需加載的庫呢,爲了實現按需加載:閉包

//這是咱們要實現的功能,require('str.js')時加載str.js文件,並建立一個叫str對象,等加載完畢以後執行str對象的ready方法裏的函數。app

var str = require('str.js');

str.ready(show);

//要執行的函數

function show(res){

    console.log(res);

}

//str.js 文件,提供"我是str"字符串

//require.js 這個是咱們要寫的庫

理一理思路

一、如何加載str.js文件呢?函數

A:咱們能夠插入一個<script src="str.js"></script>,這樣不只加載了str.js,裏面的代碼還能夠被瀏覽器自動運行呢。ui

二、如何判斷str.js文件已經加載完畢?code

A:能夠在str.js文件裏執行一個函數,通知你們,我已經加載完了。htm

三、require('str.js')返回一個對象,這個對象要怎麼和str.js相關聯呢?對象

A:咱們能夠建立一個叫JS['str.js']的對象,使str指向這個對象就好了。

四、我不想把代碼都寫進一個ready裏面,我要寫在不少個ready裏面,加載完以後它們都能執行嗎?

A:無論多少個ready,沒加載完的時候,都會丟進一個隊列裏面先保存着,因此咱們須要一個隊列。

五、加載完的那個時刻觸發ready,那加載完以後我再寫的ready函數,就不執行嗎?

A:也會執行,因此,在加載完的那個時刻,咱們將重寫ready函數。

六、這麼多東西20行代碼能完成嗎?

A:....

執行方案

根據上訴思路,寫了一個require.js文件:

function require(path){

    //好比咱們require('js/str.js') , 咱們須要獲取'str.js'這個文件名
    var filename = path.split('/');
    filename = filename[filename.length-1];

    JS[filename]={
        fn:[/*這個就是(4)中提到的那個隊列*/],

        //這是(2)中提到的方法,str.js文件裏面執行這個方法就表明它加載完了
        ready:function(){
        
            JS[filename].fn.forEach(function(fn){
                //JS['str.js'].export就是str.js要提供的東西:'我是str'
                fn(JS[filename].export);
            });

            //這是(5)中提到的,ready函數的重寫
            JS[filename].rt.ready = function(fn){
                fn(JS[filename].export);
            };
        },
        rt:{
            ready:function(fn){JS[filename].fn.push(fn)}//這個就是str對象的ready函數
        }
    };

    //這是(1)中提到的插入script標籤
    var script = document.createElement('script');
    script.src = path;
    document.head.appendChild(script);

    //這是(3)中要返回的對象
    return JS[filename].rt;
}

接下來,就差str.js的寫法了:

/*

    這裏你想寫什麼代碼都行,推薦寫在閉包裏,以避免污染全局變量

*/
JS['str.js'].export = '我是str';//這個是供你們使用的參數
JS['str.js'].ready();//執行這個函數,通知你們,str.js加載完畢了

確認一下執行結果

<!DOCTYPE html>
<script src="require.js"></script>
<script>
    var str = require('str/str.js');
    str.ready(show);

    setTimeout(function(){
        str.ready(show);
    },3000);

    //要執行的函數
    function show(res){
        console.log(res);
    }
</script>

ok,一切正常。

相關文章
相關標籤/搜索