从头开始写框架(二):孕育框架的种子_中

上一篇我们介绍了AMD规范,异步模块的定义与加载,我们完成了定义的部分。接下来,我们来完成加载的部分。

我们之前已经可以用define来定义模块了,那么现在怎么去使用的?我们只是把定义好的模块存进了仓库,用的时候还需要一个方法来使用它。

让我们先来用define来定义一些模块:

define("a" , [] , function(){ //无依赖模块
	return 1;
});

define("b" , ["a"] , function(a){ //有一个依赖的模块
	return ++a;
});

define("c" , ["a","b"] , function(a,b){ //有两个依赖的模块  一会我们要使用这个模块
	return a+b;
});

  

这里定义了3个模块,其中有一个没有依赖,两个是存在依赖模块的模块。

然后我们需要一个方法来使用定义好的模块:(对于apply和call方法不懂的话,可以移步我的另一篇文章:来聊聊apply和call)

var noop = function(){}; //为apply方法准备的一个空函数;
function use(name){ //参数:模块名
	if(modules[name]){ // 如果模块定义过:

		var module = modules[name]; //创建一个副本
		if(!module.entity){ //如果实例不存在,说明是第一次创建

			var args = [];

			for(var i=0;i<module.dependencies.length;i++){ //遍历依赖列表

				modules[module.dependencies[i]].entity ?  //依赖模块的实例以存在的话
				args.push(modules[module.dependencies[i]].entity) : //直接获取实例(缓存方法),
				args.push(this.use(module.dependencies[i])); //不然单独获取一次

			};
			
			module.entity = module.fn.apply(noop , args); //用apply方法为模块实例扩展

		};

		return module.entity; //以后调用可以直接调用缓存

	}else{

		throw new Error("Error:"+ name +" is not define"); // 如果没有定义模块,直接抛出一个错误.

	}
};

  

这里我们定义了一个使用模块的方法,通过模块名来调用定义过的模块。而使用过一次的模块,我们把它存入缓存中,这样以后再次使用时,直接调用它的实例就可以了。

那么接下来我们来用这个方法来使用我们定义好的模块:

var d = use("c");
console.log(d)//输出3

  

这样我们就能使用任意我们定义过的模块了,而重新定义模块时,不会出现模块名相同导致模块被覆盖的情况。

那么我们怎么用这个方法来扩展我们的命名空间呢?显然,define和use方法是不能直接使用的,因为我们的模块是定义在了工厂方法的参数中,而这两个方法是被定义在了工厂方法内部中,所以我们是获取不到的。

那么让我们来改造一下这两个方法

这个出自Vuejs:

var moduleMap = {}; //模块仓库

		function require(ID){ //参数为模块的名字,这里直接用数字来给模块定义id

			if(moduleMap[ID]) //如果模块已经存在
				return moduleMap[ID].exports;//直接返回实例,并结束代码块

			var module = moduleMap[ID] = { //声明一个新对象
				exports:{},//初始化实例
				id:ID,
				loaded:false//初始化加载状态
			};

			modules[ID].call(module.exports, module, module.exports, require); //用call方法将模块扩展到仓库中

			module.loaded = true; //设置模块加载状态
			
			return module.exports; //返回模块实例
		};

		return require(0); //返回第一个模块的调用

  

这个方法直接把定义模块的函数放到了工厂方法的参数里,简化了很多程序,调用也更方便了。那么接下来就剩下怎样将框架模块与方法注册到命名空间上了。

这部分我们放到下一篇来写。

原文地址:https://www.cnblogs.com/BlueQ/p/5045649.html