zoukankan      html  css  js  c++  java
  • 从头开始写框架(二):孕育框架的种子_中

    上一篇我们介绍了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); //返回第一个模块的调用
    

      

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

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

  • 相关阅读:
    Selenium学习之==>常见面试题
    Selenium学习之==>Switch与SelectApi接口详解
    Selenium学习之==>ActionChainsApi接口详解
    Selenium学习之==>WebDriverApi接口详解
    Selenium学习之==>三种等待方式
    Selenium学习之==>18种定位方式的使用
    avaScript 的基础学习(一)
    前端基础之CSS
    Http协议
    前端基础之html
  • 原文地址:https://www.cnblogs.com/BlueQ/p/5045649.html
Copyright © 2011-2022 走看看