锁定老帖子 主题:JS架构探讨-精彩討論进行中...
精华帖 (0) :: 良好帖 (12) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-05-17
最后修改:2011-05-24
坦克大战小游戏,感谢大家热情回复,但从此中也发现前台开发人员水平参差,而且从接触到的同行可以看出,这方面大家的理解差距较大。
此前做过一个
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> <input type="text" id="username" /><br />') .append('<label class="password">password: </label> <input type="password" id="password" /><br />') .append('<label class="gender">gender: </label> <select id="gender"><option>male</option><option>female</option></select><br />') .append('<input type="button" id="submit" value="submit" /> <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> 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-05-18
新浪的前端架构蛮好的。
前端交互要求越高,对规范性的要求就更高呀 |
|
返回顶楼 | |
发表时间:2011-05-18
新浪的前端架构蛮好的。
前端交互要求越高,对规范性的要求就更高呀 |
|
返回顶楼 | |
发表时间:2011-05-18
新浪的前端架构蛮好的。
前端交互要求越高,对规范性的要求就更高呀 |
|
返回顶楼 | |
发表时间:2011-05-18
ydzhony1写道:
引用 你这个demo功能是什么?
没看懂. 这个怪我,时间仓促,没能解释清楚。 这个DEMO主要是实现了创建类及继承,命名空间及包内权限,导入模块包。 每个页面由若干功能,每个功能由一个或多个模块实现。这个DEMO通过index页面的登陆和切换用户两个功能,分别对应了两个模块的具体实现,简单阐述了这个思路。 希望大家使劲拍砖,让这篇文章实现她的意义,以帮助更多的人。 |
|
返回顶楼 | |
发表时间:2011-05-18
我正在深入前端,先MARK下
|
|
返回顶楼 | |
发表时间:2011-05-18
你实现继承的思路跟我一开始的想法是差不多的。将父类元素写在参数的最后。但是这样带来一个问题。如果子类内容很多,那么要看他继承了哪个父类就很难看清楚了。所以我的继承实现里才会把子类元素放在后面,而父类放在最前面。和var定义写在一行
|
|
返回顶楼 | |
发表时间:2011-05-18
个人也不太崇尚prototype继承实现
同样的功能用prototype会写成这样。 var Animal = function() {}; Animal.prototype = { ... }; 属性和方法必须分开写 但是根据ECMAScript5最新的理解。 var Animal = { ... }; 写成这样就足够了。可以用Object.create去创建。 详细说明可以参考我的blog http://www.iteye.com/topic/1026530 |
|
返回顶楼 | |
发表时间:2011-05-18
至于在底层中用jq,本人持保留意见。。
|
|
返回顶楼 | |
发表时间:2011-05-18
最后修改:2011-05-18
rainsilence 写道 你实现继承的思路跟我一开始的想法是差不多的。将父类元素写在参数的最后。但是这样带来一个问题。如果子类内容很多,那么要看他继承了哪个父类就很难看清楚了。所以我的继承实现里才会把子类元素放在后面,而父类放在最前面。和var定义写在一行
很高兴听到您的意见,俗话说众人拾柴火焰高,我相信利用大家的力量,一定可以把这个小DEMO最终实现为一个开源的,公共的基础框架。 PS:至于jQuery既是权宜之计,也符合大多数小公司的现状,我想以后会换掉,也许会像新浪的那样,颗粒度极小,功能强大,这都需要大家出力撒。 |
|
返回顶楼 | |