代码改变世界

javascript 构建模块化开发

2019-05-20 14:49  muamaker  阅读(468)  评论(0编辑  收藏  举报

在使用 sea.js 、require.js 、 angular 的时候。

我们使用到  define 、 module(require) 的方式,定义模块,和依赖模块

下面给出 define 和 module 的简单实现。 其本质,就是往一个对象上面添加方法

 

	var F = {};
	F.define = function(str,fn){
		var parts = str.split(".");
		var parent = this; // parent 当前模块的父模块
		var i = len = 0;
		
		//如果第一个模块是模块单体对象,则移除
		if(parts[0] == "F"){
			parts = parts.slice(1);
		}
		
		//屏蔽对 define module 模块方法重写
		if(parts[0] == "define" || parts[0] == "module"){
			return ;
		}			
		
		for(len = parts.length; i < len-1; i++){
			//如果父模块中不存在当前模块
			if(typeof parent[parts[i]] === 'undefined'){
				//声明当前模块
				parent[parts[i]] = {};
			}
			//缓存下一层父模块
			parent = parent[parts[i]];
		}
		
		if(fn && parts[i]){
			//如果给定模块方法,则绑定该模块的方法,
			parent[parts[i]] = fn();
		}
		return this;
	}
	
	F.module = function(){
		var args = [].slice.call(arguments);//复制参数
		var fn = args.pop(); //获取回调
		
		var parts = args[0] && args[0] instanceof Array ? args[0] : args;
		
		//模块的依赖
		var modules = [];
		
		//模块的路由
		var modIDs = "";
		
		//依赖模块的索引
		var i = 0;
		
		var len = parts.length; // 依赖模块的长度
		
		var parent,j,jlen; //父级模块,模块路由层级索引,模块路由层级长度
		
		while(i < len){
			if(typeof parts[i] == "string"){
				parent  = this;
				//解析路由,并且屏蔽掉 F 
				modIDs = parts[i].replace(/^F\./,"").split(".");
				//遍历模块层级
				for( j = 0,jlen = modIDs.length; j < jlen; j++){
					//迭代 父模块
					parent = parent[modIDs[j]] || false;
				}
				modules.push(parent); //将模块添加到依赖列表
			}else{
				//直接将模块添加到依赖列表
				modules.push(parts[i]);
			}
			//取下一个模块
			i++;
		}
		
		
		//执行回调,将依赖的模块注入
		fn.apply(null,modules);
		
	}
	
	//定义 string 模块
	F.define("string",function(){
		return {
			trim(str){
				return str.replace(/^s+|\s+$/g,"");
			}
		}
	});
	//定义 string 模块,的子模块 sub
	F.define("string.sub",function(){
		return {
			low(str){
				return str.toLowerCase();
			}
		}
	});
	console.log(F);
	
	
	//使用模块
	F.module(["string","string.sub",document],function(str,strSub,doc){
		console.log(str,strSub,doc)
	});
	

  

 

当然了,这里使用的,F 对象,实际应用中,应该写在闭包里面。不能让外界直接访问,于是有如下代码。

 

 

	var Sea = (function(){
		var F = {};
			F.define = function(str,fn){
			var parts = str.split(".");
			var parent = this; // parent 当前模块的父模块
			var i = len = 0;
			
			//如果第一个模块是模块单体对象,则移除
			if(parts[0] == "F"){
				parts = parts.slice(1);
			}
			
			//屏蔽对 define module 模块方法重写
			if(parts[0] == "define" || parts[0] == "module"){
				return ;
			}			
			
			for(len = parts.length; i < len-1; i++){
				//如果父模块中不存在当前模块
				if(typeof parent[parts[i]] === 'undefined'){
					//声明当前模块
					parent[parts[i]] = {};
				}
				//缓存下一层父模块
				parent = parent[parts[i]];
			}
			
			if(fn && parts[i]){
				//如果给定模块方法,则绑定该模块的方法,
				parent[parts[i]] = fn();
			}
			return this;
		}
		
		F.module = function(){
			var args = [].slice.call(arguments);//复制参数
			var fn = args.pop(); //获取回调
			
			var parts = args[0] && args[0] instanceof Array ? args[0] : args;
			
			//模块的依赖
			var modules = [];
			
			//模块的路由
			var modIDs = "";
			
			//依赖模块的索引
			var i = 0;
			
			var len = parts.length; // 依赖模块的长度
			
			var parent,j,jlen; //父级模块,模块路由层级索引,模块路由层级长度
			
			while(i < len){
				if(typeof parts[i] == "string"){
					parent  = this;
					//解析路由,并且屏蔽掉 F 
					modIDs = parts[i].replace(/^F\./,"").split(".");
					//遍历模块层级
					for( j = 0,jlen = modIDs.length; j < jlen; j++){
						//迭代 父模块
						parent = parent[modIDs[j]] || false;
					}
					modules.push(parent); //将模块添加到依赖列表
				}else{
					//直接将模块添加到依赖列表
					modules.push(parts[i]);
				}
				//取下一个模块
				i++;
			}
			
			
			//执行回调,将依赖的模块注入
			fn.apply(null,modules);
		}
		return {
			define:function(){
				F.define.apply(F,arguments);
			},
			module:function(){
				F.module.apply(F,arguments);
			}
		}
	})();

	
	//定义 string 模块
	Sea.define("string",function(){
		return {
			trim(str){
				return str.replace(/^s+|\s+$/g,"");
			}
		}
	});
	//定义 string 模块,的子模块 sub
	Sea.define("string.sub",function(){
		return {
			low(str){
				return str.toLowerCase();
			}
		}
	});
	console.log(Sea);

	//使用模块
	Sea.module(["string","string.sub",document],function(str,strSub,doc){
		console.log(str,strSub,doc)
	});