小菜鸡的require.js源码之旅 —— (一)

一、require使用方法

require遵循AMD规范
也就是通过在加载模块时注册回调函数的方式,当所需模块加载完成后,再去执行回调
这样就保证了不会因所需模块未加载而造成的错误

<script src="./js/require.js" data-main="./js/main.js"></script>

使用时需要加上data-main属性,指向脚本文件的入口文件位置

二、开始分析

1.给定了入口文件位置,第一步肯定要找到入口文件具体额位置

#2007-#2052

于是我发现了下面这段代码:

//Look for a data-main script attribute, which could also adjust the baseUrl.
if (isBrowser && !cfg.skipDataMain) {
    //Figure out baseUrl. Get it from the script tag with require.js in it.
    eachReverse(scripts(), function (script) {
        //Set the 'head' where we can append children by
        //using the script's parent.
        if (!head) {
            head = script.parentNode;
        }

        //Look for a data-main attribute to set main script for the page
        //to load. If it is there, the path to data main becomes the
        //baseUrl, if it is not already set.
        dataMain = script.getAttribute('data-main');
        if (dataMain) {
			// ........... 此处省略一万字
            return true;
        }
    });
}

isBrowser 判断了是否是浏览器环境

isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && window.document)

这种判断方式确实以前没有见到过!

2. 之后进入到eachReverse函数中

/**
     * Helper function for iterating over an array backwards. If the func
     * returns a true value, it will break out of the loop.
     */
function eachReverse(ary, func) {
        if (ary) {
            var i;
            for (i = ary.length - 1; i > -1; i -= 1) {
                if (ary[i] && func(ary[i], i, ary)) {
                    break;
                }
            }
        }
    }

官方给的注释也非常详细,这是一个用于迭代一个数组中的每个成员的函数,且回调函数func执行结果为true时便会立即退出迭代过程
调用此函数第一步传入scripts()函数的返回值
这个函数没什么好说的,返回全部的script标签数组

function scripts() {
       return document.getElementsByTagName('script');
}

然后相当于遍历了所有的script标签,直到取到一个带有data-main属性的标签

dataMain = script.getAttribute('data-main');
if (dataMain) {
    mainScript = dataMain;
    //==========================================================
    //如果没有定义配置对象中的baseUrl 并且 此路径不是插件
    //require.js中使用!表示插件
    //==========================================================
    if (!cfg.baseUrl && mainScript.indexOf('!') === -1) {
        //Pull off the directory of data-main for use as the
        //baseUrl.
        src = mainScript.split('/');
        mainScript = src.pop();
        subPath = src.length ? src.join('/')  + '/' : './';

        cfg.baseUrl = subPath;
        //==========================================================
        //这里应该是对不同情况下的入口文件路径做了适配
        /*
        比如路径是"./js/index.js"
        先切分成数组src = [".","js","index.js"]
        mainScript = "."
        src = [".","js"]
        subPath = 2 ? src.join('/')  + '/' : './' = src.join('/')  + '/' 
        = "./js/"
        之后赋值给baseUrl 也就做到了默认读取其他模块从此路径下进行读取
        */
        //==========================================================
    }
    //==========================================================
    去掉文件结尾的.js文件
    //==========================================================
    mainScript = mainScript.replace(jsSuffixRegExp, '');
    if (req.jsExtRegExp.test(mainScript)) {
        mainScript = dataMain;
    }
    cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript];

    return true;
}

参考资料

阮一峰老师的博客——js模块化编程
require.js下载(学习的话选择有注释的版本就行了(With Comments))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值