`
danny.chiu
  • 浏览: 89419 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JS架构探讨-精彩討論进行中...

阅读更多
    此前做过一个坦克大战小游戏,感谢大家热情回复,但从此中也发现前台开发人员水平参差,而且从接触到的同行可以看出,这方面大家的理解差距较大。

    JS前景很好,2014年HTML5标准更新之后,在很长的时间内,她都会越来越流行,特别是在游戏横行,移动设备更新快,很多人又不愿意用各种软件把手机弄得半死不活的今天,JS在移动设备上可能可能首先打败flash,成为前端的一哥。

    为什么要写此文?不可否认JS越来越流行,因为她灵活,什么样的水平都可以写出能实现功能的代码;这也突显出一个尖锐的问题:代码规范化。至于架构的重要性,我想不用多说,无非是规范代码、提高重用性、易扩展易维护。百度、新浪、豆瓣等都有自己的架构,今天在下分享一个DEMO,希望抛砖引玉,懂行的不要保留,分享是金;顺便把新浪架构PPT分享给大家。

    个人对架构的理解,无非是分层和模块化,以下代码主要基于此理解。使用jQuery作为底层,模块为中层,功能为上层、模块的组合。我们的目的是用此框架,我们可以把注意力集中在模块开发上,以实现易扩展、易重用、规范化的目标。

    待完善的地方有很多,比如针对每个页面独立一个配置文件(例如JSON),服务器端把此页面用到的JS合并压缩,以减少请求数,等,期待大家提出更多更好的建议。


核心实现:
constructor/js/aispeech.js
var AIS = (function() {
	var ONE_PROP = 'test'; // 私有属性和私有方法,只供框架内部使用
	return {
		create: function(obj, supr) { // 创建类或子类
			var sb = obj.initialize, sp;
			delete obj.initialize;
			if (!supr || typeof supr === 'object') {
				sb.prototype = obj;
			} else {
				sp = function() {};
				sp.prototype = supr.prototype;
				sb.prototype = new sp();
				sb.supr = sp.prototype;
				$.extend(sb.prototype, obj);
			}
			sb.prototype.constructor = sb;
			return sb;
		},
		getScript: function(url, cb) { // 引入js文件
			$.getScript(url, cb);
		},
		modual: {}, // 注册模块及其路径
		namespace: function(ns, cb) { // 命名空间
			var nsArr = ns.split('.'), o;
			o = window[nsArr[0]] = window[nsArr[0]] || {};
			$.each(nsArr.slice(1), function(i, n) {
				o = o[n] = o[n] || {};
			});
			AIS.modual[nsArr.slice(-1)].ns = ns;
			if (cb && typeof cb === 'function') cb.call(o);
		},
		importMD: function(modual, cb) { // 导入模块,根据模块名
			cb = cb || function() {};
			if (AIS.modual[modual].ns) {
				cb.call(eval(AIS.modual[modual].ns));
			} else {
				AIS.getScript(AIS.modual[modual].url, function() {
					cb.call(eval(AIS.modual[modual].ns));
				});
			}
		},
		util: { // 工具集
			isEmptyObject: function(obj) {
				for (var prop in obj) {
					return false;
				}
				return true;
			},
			toArray: function(arrLike) {
				return Array.prototype.slice(arrLike);
			},
			// browsers..
			isIE: function() {
				return !-[1,];
			}
		}
	}
})();

使用方法:
var A = AIS.create({
	initialize: function(name) { // 每个类都必须声明的构造器方法
		this.name = name;
	},
	hello: function() {
		alert('hello: '+ this.name);
	}
});
var a = new A('danny');
a.hello();
var B = AIS.create({  // B继承自A
	initialize: function(name, age) {
		B.supr.constructor.call(this, name);
		this.age = age;
	},
	world: function() {
		alert('world: '+ this.age);
	}
}, A);

一个用户登陆和切换用户的DEMO:
constructor/ais.modual.js
AIS.modual = {
	'login': {
		'url': 'js/login/login.js'
	},
	'switcher': {
		'url': 'js/login/switch.js'
	}
}

constructor/js/login/login.js
AIS.namespace('com.ais.aid201105.login', function() {
	//var PrivateClass = AIS.create({...}); 可以创建包内私有的类
	this.LoginForm = AIS.create({ // public class
		initialize: function(pid) {
			this.parentId = pid;
			this.initForm();
			this.submit();
		},
		initForm: function() {
			var $f = $('<form></form>');
			$f.append('<fieldset style="width: 250px;"></fieldset>').find('fieldset')
			.append('<legend>Login Form</legend>')
			.append('<label class="username">name: </label>&nbsp;<input type="text" id="username" /><br />')
			.append('<label class="password">password: </label>&nbsp;<input type="password" id="password" /><br />')
			.append('<label class="gender">gender: </label>&nbsp;<select id="gender"><option>male</option><option>female</option></select><br />')
			.append('<input type="button" id="submit" value="submit" />&nbsp;<input type="reset" value="reset" />');
			$('#' + this.parentId).html($f).show('slow').find('#username').focus();
			$('.username, .password, .gender').css({
				'display': 'inline-block',
				'width': '70px',
				'text-align': 'right'
			});
		},
		submit: function() {
			var that = this;
			$('#submit').click(function() {
				//alert('name: ' + $('#username').val() + '\npassword: ' + $('#password').val()); // submit check
				$('#' + that.parentId).hide();
				$('#welcome').find('span').text($('#username').val()).end().show();
			});
		}
	});
});

切换用户引用登陆
constructor/js/login/switch.js
AIS.namespace('com.ais.aid201105.switcher', function() {
	this.Switch = AIS.create({
		initialize: function(sid, lid) {
			this.switchId = sid;
			this.lid = lid;
			this.attachEvent();
		},
		attachEvent: function() {
			var that = this;
			$('#switch').click(function() {
				AIS.importMD('login', function() {
					new this.LoginForm(that.lid);
				});
				$('#welcome').hide();
			});
		}
	});
});


constructor/js/index.js
$(function() { // index
	AIS.importMD('login', function() {
		new this.LoginForm('login_md');
	});

	AIS.importMD('switcher', function() {
		new this.Switch('switch', 'login_md');
	});

})


constructor/index.html
<!DOCTYPE HTML>
<html>
	<head>
		<script type="text/javascript" src="js/jquery-1.6.min.js"></script>
		<script type="text/javascript" src="js/aispeech.js"></script>
		<script type="text/javascript" src="js/ais.modual.js"></script>
		<script type="text/javascript" src="js/index.js"></script>
	</head>
	<body>
		<div id="welcome" style="display: none;">欢迎<b><span></span></b> | <a 

href="#" id="switch">切换用户</a></div>
		<div id="login_md"></div>
	</body>
</html>
  • 大小: 14.4 KB
分享到:
评论
29 楼 zxmlgh 2011-05-19  
还是更喜欢mootool
28 楼 zhangcs053 2011-05-19  
前端将越来越重要。
27 楼 liuzhuo84 2011-05-19  
rainsilence 写道
wu_yong988 写道
讨论一下:
switch.js和switch.js能不能在用的时候才加载某个呢?
这样在模块多的时候,性能会有很大提升。


你说的这个原理很简单啊。。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-31j">
<title>Insert title here</title>
<script type="text/javascript">
	function importScript(scriptPath, callback) {
		var headTag = document.getElementsByTagName("head")[0];
		
		var scriptTag = document.createElement("script");
		scriptTag.type = "text/javascript";
		var isOver = false;
		scriptTag.onload = function() {
			if (isOver) {
				return;
			}
			isOver = true;
			callback();

		}
                // IE9/10同时支持onreadystatechange & onload
		scriptTag.onreadystatechange = function() {
			
			if (isOver) {
				return;
			}
			
			isOver = true;
			if (this.readyState == 'loaded' || this.readyState == 'complete') {
				callback();
			}
		};
		scriptTag.src = scriptPath;
		headTag.appendChild(scriptTag);
	}
	window.onload = function() {
		importScript("a.js", function() {test();});
	};
</script>
</head>
<body>

</body>
</html>


高手!可不可以用异步请求的方式去请求js文件,回来之后eval一下。如下:不知道可行不?
$.ajax({
    url: 'a.js',
    type: 'GET',
    timeout: 1000,
    success: function(text){
        eval(text);
    }
});
26 楼 liuzhuo84 2011-05-19  
linkobe 写道
怎么现在动不动都喜欢谈架构、模块化开发,以前做后端的时候总听到ioc,aop,现在做前端了,又开始一坨的模块、继承。难道现在只要是项目没有不大到不得不模块化开发的境界?


不是非要大才要模块化,模块化是为了复用,复用既可以是但项目内的,也可以是项目之间的。模块化的东西可以形成团队的过程资产。
25 楼 linkobe 2011-05-19  
怎么现在动不动都喜欢谈架构、模块化开发,以前做后端的时候总听到ioc,aop,现在做前端了,又开始一坨的模块、继承。难道现在只要是项目没有不大到不得不模块化开发的境界?
24 楼 yolio2003 2011-05-19  
我看了后只是觉得 淘宝大牛的 seajs 满足模块化的需求,但是继承就要另外实现了
23 楼 rainsilence 2011-05-19  
加班到现在。随便看看,发现又多了张图。。
设计上的问题:
1.constructor/ais.modual.js设计出来了干嘛呢?mapping吗?没有必要啊
用我写给楼上的代码就ok了。你改改可以这样调用
importScript("js.com.util", function() {.....});
你的mapping没有必要啊。
2.你的create方法写成了单继承。但是js天生是多继承的。。
3.jq,jq,jq.....

拜读了sina的framework,发现最有价值的是最后的uml图。不过貌似不是原创。天下文章大家抄的感觉。
22 楼 wu_yong988 2011-05-18  
果然是高手!:)
21 楼 rainsilence 2011-05-18  
a.js:
function test() {
    alert(123);
}
20 楼 rainsilence 2011-05-18  
wu_yong988 写道
讨论一下:
switch.js和switch.js能不能在用的时候才加载某个呢?
这样在模块多的时候,性能会有很大提升。


你说的这个原理很简单啊。。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-31j">
<title>Insert title here</title>
<script type="text/javascript">
	function importScript(scriptPath, callback) {
		var headTag = document.getElementsByTagName("head")[0];
		
		var scriptTag = document.createElement("script");
		scriptTag.type = "text/javascript";
		var isOver = false;
		scriptTag.onload = function() {
			if (isOver) {
				return;
			}
			isOver = true;
			callback();

		}
                // IE9/10同时支持onreadystatechange & onload
		scriptTag.onreadystatechange = function() {
			
			if (isOver) {
				return;
			}
			
			isOver = true;
			if (this.readyState == 'loaded' || this.readyState == 'complete') {
				callback();
			}
		};
		scriptTag.src = scriptPath;
		headTag.appendChild(scriptTag);
	}
	window.onload = function() {
		importScript("a.js", function() {test();});
	};
</script>
</head>
<body>

</body>
</html>
19 楼 rainsilence 2011-05-18  
wu_yong988 写道
rainsilence 写道
Line 52:
Array.prototype.slice(arrLike);
这个??????

Array.prototype.slice.call(arrLike);
这个吧。。

啊?我说的和这个有关吗?


我还没看到你说的话呢。。我是说这是个bug
18 楼 wu_yong988 2011-05-18  
rainsilence 写道
Line 52:
Array.prototype.slice(arrLike);
这个??????

Array.prototype.slice.call(arrLike);
这个吧。。

啊?我说的和这个有关吗?
17 楼 rainsilence 2011-05-18  
Line 52:
Array.prototype.slice(arrLike);
这个??????

Array.prototype.slice.call(arrLike);
这个吧。。
16 楼 wu_yong988 2011-05-18  
讨论一下:
switch.js和switch.js能不能在用的时候才加载某个呢?
这样在模块多的时候,性能会有很大提升。
15 楼 danny.chiu 2011-05-18  
lokinell2006 写道
个人觉得现在dojo的整体架构做的不错
分为core, base, dijit 和 dojox
多看看dojo的源码相信对于面向对象的JS有莫大的帮助。

期待您提出宝贵意见,一起完善这个DEMO,分享给更多人。
14 楼 danny.chiu 2011-05-18  
yinchunjian 写道
AIS.importMD('login', function() {
var a = new this.LoginForm('login_md');
a.a();
});
能否一下子引入所有类
然后再具体创建一个类对象对其操作

这个问题要看情况啊,如果所有类定义在一个文件里就可以,如果定义在多个文件,需要把AIS.modual[模块名]对应的url改成数组,选择加载。
13 楼 lokinell2006 2011-05-18  
个人觉得现在dojo的整体架构做的不错
分为core, base, dijit 和 dojox
多看看dojo的源码相信对于面向对象的JS有莫大的帮助。
12 楼 yinchunjian 2011-05-18  
AIS.importMD('login', function() {
var a = new this.LoginForm('login_md');
a.a();
});
能否一下子引入所有类
然后再具体创建一个类对象对其操作
11 楼 yinchunjian 2011-05-18  
请问 如果我想调用 LoginForm 类里面的方法怎么写 还有就是我想在类里定义一个方法供供类中其他方法使用怎么写
10 楼 zsuantou 2011-05-18  
mark一下
以前编写js都是用到哪个方法就写个function,很少考虑到继承、复用之类的东西

相关推荐

    藏经阁-技术人的百宝黑皮书-1671.pdf

    除了技术总结,书中还包含了前端人精彩问答环节,这部分可能涵盖了实际开发中遇到的问题、最佳实践以及前沿技术的讨论,为读者提供了深入学习和交流的平台。 **音视频与实时通信** 在音视频技术部分,书中提及了将...

    毕业论文java vue springboot mysql 冬奥会科普平台.docx

    - **精彩视频管理**:上传、编辑和展示冬奥会精彩视频。 - **冬奥论坛**:用户交流讨论的平台,支持发帖、回帖、点赞等操作。 - **系统管理**:后台管理功能,如数据备份、日志监控等。 4. **数据库设计**: - ...

    ASP源码—足球资讯网站源码 v5.32.zip

    5. **论坛讨论**:用户可以在此板块进行足球话题的交流和讨论。 6. **用户系统**:注册登录功能,允许用户保存个性化设置,如收藏的球队、关注的比赛等。 7. **数据统计**:统计球队和球员的表现数据,如进球数、...

    【最新完整版】软件开发大会2021-PPT完整版

    2. **编程语言与框架**:大会可能会讨论各种编程语言的新特性,如Java、Python、JavaScript的最新版本,以及React、Angular、Vue等前端框架的更新和最佳实践。 3. **微服务与容器化**:随着微服务架构的广泛应用,...

    must-watch-javascript:有关JavaScript的必看话题的有用列表

    这些资源包括React、AngularJS、jQuery、Angular、ReactJS等流行的JavaScript框架,以及关于异步JavaScript、JavaScript框架的会议演讲、Netflix相关的技术探讨,还有dotJS和JSConf这样的顶级会议的演讲视频。...

    Web开发敏捷之道第三版(中文版).pdf

    本书《Web开发敏捷之道第三版》是一本深入探讨如何使用Ruby on Rails框架进行高效、敏捷的Web开发的技术书籍。书中通过一个完整的示例项目——Depot应用程序,循序渐进地介绍了Rails框架的核心概念和技术,并结合...

    2017第三届PHP全球开发者大会ppt

    6. PHP与其他技术的集成:如与JavaScript框架(如React、Vue.js)、大数据处理(如Redis、MongoDB)、云计算平台(如AWS、Azure)的集成,展示了PHP在现代Web开发中的多元化角色。 【描述】"PHP大咖们的精彩分享,...

    移动开发大会精彩PPT

    本篇将详细探讨在移动开发大会中涉及的几个关键知识点。 首先,我们关注的是Android资源管理机制。Android作为全球最流行的智能手机操作系统,其资源管理对于开发者来说至关重要。资源管理包括对应用程序UI元素、...

    美团2018年货前端技术

    Vue.js是一个流行的JavaScript框架,具有简单、易用和灵活性高特点,适用于开发响应式和组件化的Web应用。mpvue结合了Vue.js与微信小程序的特点,为开发者提供了一种能够在微信小程序平台上使用Vue.js开发全新体验的...

    QCon北京2018 PPT合集

    在《QCon北京2018 PPT合集中》,你可以找到专家们对新兴技术的深度解析,包括如何利用机器学习进行预测分析,如何构建高效稳定的云平台,以及如何优化微服务架构以提高系统的可扩展性和容错性。此外,还有关于...

    Agile Web Development with Rails中文版 3rd Edition

    讨论了如何评估应用的性能并进行优化。 **14.6 使用Mock对象** 讲解了如何使用Mock对象来模拟对象的行为,以便于测试。 #### 十五、深入Rails 这部分提供了更深层次的技术细节。 **15.1 Rails在哪儿** 介绍了...

    PghTechFest2015:演讲者发布的材料,来自匹兹堡TechFest 2015

    参与者可能还分享了如何将Ruby与其他技术集成,如JavaScript前端框架(如React或Vue.js)、数据库系统(如PostgreSQL或MongoDB)以及持续集成/持续部署(CI/CD)工具(如Jenkins或Travis CI)。此外,他们可能还探讨...

Global site tag (gtag.js) - Google Analytics