(一)requireJs 的整体结构:

  requireJS 源码 前192行,是一些 变量的声明,工具函数的实现 以及 对 三个全局变量(requirejs,require,define)若被占用后的具体处理。

     从 194行到 1674行,整整 1480行,是 实例化上下文 函数 newContext() 。

  在 在req({ } ) 调用时执行 newContext函数,而且只会执行一次。

  从1690行开始,便是对外API  require/requirejs/define  的具体实现。

(二)简单的demo 层级。

  

 require.config({
//根基目录baseUrl:'',
paths: {
app: 'src/app'
}
}); /**
* Require 默认指定的所有资源都是JS文件,不需要在module 上添加.js后缀
*
* */
require([
'src/app'
], function (app) {
app.sayBy('美丽的女孩 Rose');
app.sayGood("美丽的女孩 Lily");
})

main.js

 define(['./person'],function (person) {
var sayGood = function (name) {
console.log('早上好 ' + name);
}; var sayBy = function (name) {
console.log(person.run());
console.log('再见 ' + name);
}; return {
sayGood: sayGood,
sayBy: sayBy
}
});

app.js

define(function(require,exports,module){
exports.run=function(){
console.log('there is a person run....');
}
});

person.js

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

index.html

 从index.html 中,我们看到<script data-main="main" src="lib/require.js"></script>

采用了 data-main 这样一个自定义属性,指定了入口js文件。跟着这条线,我们可以进入requireJS的大门。

(三)源码分析
  1762行会创建 默认上下文执行环境
                
  使用 require('person'),便是调用了这个函数。
  首次调用时,便会创建 default context,
  这是因为req() ===> 调用了 function newContext()。
  在1922行代码处,开始处理 data-main 属性值,去加载我们这里的main.js文件。
                  
 
 //Look for a data-main script attribute, which could also adjust the baseUrl.
/**
* 判断是否在浏览器中运行(requireJS不止用在浏览器中)
* */
if (isBrowser && !cfg.skipDataMain) {
//Figure out baseUrl. Get it from the script tag with require.js in it.
/**
* 通过 document.getElementsByTagName('script') 拿到所有 script 的标签集合(HTMLCollection)
* */
eachReverse(scripts(), function (script) { /**然后使用 eachRevers() 倒序 script 里面的内容
* head = 如果不存在 base标签 ? head 标签元素 : base.parentNode
* 如果head不存在,拿到script里面的父元素
*/
if (!head) {
head = script.parentNode;
} dataMain = script.getAttribute('data-main'); /**dataMain= main.js*/
if (dataMain) {
//Preserve dataMain in case it is a path (i.e. contains '?')
mainScript = dataMain; //Set final baseUrl if there is not already an explicit one.
if (!cfg.baseUrl) {
/**
* src 已经变成数组,出队列,mainScript=main.js
* */
src = mainScript.split('/');
mainScript = src.pop();
subPath = src.length ? src.join('/') + '/' : './'; /***
* src.length=0,cfg.baseUrl='./'
* 目的是与 main.js 统一目录
* */
cfg.baseUrl = subPath;
} /** 正则匹配,mainScript=main,此时去掉 .js 后缀,看起来更像是一个 module */
mainScript = mainScript.replace(jsSuffixRegExp, ''); //If mainScript is still a path, fall back to dataMain
if (req.jsExtRegExp.test(mainScript)) {
mainScript = dataMain;
} /** 将主入口js文件放入 加载的配置文件列表中,将对 main.js 进行加载 ---req(cfg) */
cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript]; return true;
}
});
}

  经过上述代码的处理,cfg.deps值已经发生改变,已包括 main.js,接下来便要去获取 main.js中的内容,以及与它相关联的内容。

  

 

requireJS 源码(二) data-main 的加载实现的更多相关文章

  1. 【requireJS源码学习02】data-main加载的实现

    前言 经过昨天的学习,我们大概了解到了requireJS的主要结构,这里先大概的回顾一下 首先从总体结构来说,require这里分为三块: ① newContext之前变量声明或者一些工具函数 ② n ...

  2. wemall app商城源码Android之ListView异步加载网络图片(优化缓存机制)

    wemall-mobile是基于WeMall的android app商城,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可定制修改.本文分享wemall app商城源码Android之L ...

  3. 【Spring源码分析】非懒加载的单例Bean初始化过程(下篇)

    doCreateBean方法 上文[Spring源码分析]非懒加载的单例Bean初始化过程(上篇),分析了单例的Bean初始化流程,并跟踪代码进入了主流程,看到了Bean是如何被实例化出来的.先贴一下 ...

  4. 【Spring源码分析】非懒加载的单例Bean初始化前后的一些操作

    前言 之前两篇文章[Spring源码分析]非懒加载的单例Bean初始化过程(上篇)和[Spring源码分析]非懒加载的单例Bean初始化过程(下篇)比较详细地分析了非懒加载的单例Bean的初始化过程, ...

  5. Spring源码分析:非懒加载的单例Bean初始化前后的一些操作

    之前两篇文章Spring源码分析:非懒加载的单例Bean初始化过程(上)和Spring源码分析:非懒加载的单例Bean初始化过程(下)比较详细地分析了非懒加载的单例Bean的初始化过程,整个流程始于A ...

  6. Spring源码分析:非懒加载的单例Bean初始化过程(下)

    上文Spring源码分析:非懒加载的单例Bean初始化过程(上),分析了单例的Bean初始化流程,并跟踪代码进入了主流程,看到了Bean是如何被实例化出来的.先贴一下AbstractAutowireC ...

  7. spring源码学习之bean的加载(二)

    这是接着上篇继续写bean的加载过程,好像是有点太多了,因为bean的加载过程是很复杂的,要处理的情况有很多,继续... 7.创建bean 常规的bean的创建时通过doCreateBean方法来实现 ...

  8. 1. spring5源码 -- Spring整体脉络 IOC加载过程 Bean的生命周期

    可以学习到什么? 0. spring整体脉络 1. 描述BeanFactory 2. BeanFactory和ApplicationContext的区别 3. 简述SpringIoC的加载过程 4. ...

  9. Spring源码:Spring IoC容器加载过程(2)

    Spring源码版本:4.3.23.RELEASE 一.加载XML配置 通过XML配置创建Spring,创建入口是使用org.springframework.context.support.Class ...

  10. vscode源码分析【八】加载第一个画面

    第一篇: vscode源码分析[一]从源码运行vscode 第二篇:vscode源码分析[二]程序的启动逻辑,第一个窗口是如何创建的 第三篇:vscode源码分析[三]程序的启动逻辑,性能问题的追踪 ...

随机推荐

  1. Python 随机生成有效手机号码及身份证

    中国那么大,人那么多,几乎人手一部手机.手机号码已经作为各大互联网站的注册账户.同样,身份证更是如此.以下是生成有效手机号码和身份证号. 身份证需要下载districtcode.txt这个文件:htt ...

  2. struts2.1.6教程三、在Action获取Scope对象

    引言:在前面的Action操作中,关键就是Action中的exectue方法,但是此方法并没有request.session.application等对象作为参数,自然就不能利用这些对象来操作.下面我 ...

  3. sublime工具篇

    sublime快捷键的应用 熟悉掌握sublime快捷键,提高编码效率,享受编码乐趣. window操作系统常用快捷键 win+D:快速显示桌面     win+方向键:最大化最小化窗口  win+L ...

  4. JMeter命令行方式运行时动态设置线程数及其他属性(动态传参)

    在使用JMeter进行性能测试时,以下情况经常出现: 1.测试过程中,指定运行的线程数.指定运行循环次数不断改变: 2.访问的目标地址发生改变,端口发生改变,需要改写脚本. 上面的问题在GUI中,直接 ...

  5. THE R QGRAPH PACKAGE: USING R TO VISUALIZE COMPLEX RELATIONSHIPS AMONG VARIABLES IN A LARGE DATASET, PART ONE

    The R qgraph Package: Using R to Visualize Complex Relationships Among Variables in a Large Dataset, ...

  6. 中文分词中的战斗机-jieba库

    英文分词的第三方库NLTK不错,中文分词工具也有很多(盘古分词.Yaha分词.Jieba分词等).但是从加载自定义字典.多线程.自动匹配新词等方面来看. 大jieba确实是中文分词中的战斗机. 请随意 ...

  7. css因Mime类型不匹配而被忽略,怎么解决

    问题:在火狐.谷歌都可以正常显示出来,在别人的IE浏览器上也可以正常显示出来,但是在自己的ie浏览器就完全不能加载的熬样式了 控制台报告 SEC7113: CSS 因 Mime 类型不匹配而被忽略 答 ...

  8. AngularJs 第三节随笔

    利用$scope暴露模型数据 利用向控制器传递$scope对象的机制,可以把模型数据暴露给试图.在你的应用中可能还有其他数据,但是只有通过$scope 触及这些数据,angular才会把它当成数据模型 ...

  9. Python教程(0)——介绍

    What's Python? Python是一种编程语言,由荷兰人Guido van Rossum于1989年,为打发无聊的圣诞节而开发的. Python的优点是语法简洁,代码量比C/C++.Java ...

  10. Tips_of_JS 之 利用JS实现水仙花数的寻找与实现斐波那契数列

    一.水仙花数 1.啥是水仙花数? 水仙花数是指一个 n 位正整数 ( n≥3 ),它的每个位上的数字的 n 次幂之和等于它本身.(例如:1^3 + 5^3+ 3^3 = 153) 2.利用JS实现对水 ...