【发布时间】:2009-02-09 15:36:39
【问题描述】:
我正在玩弄一个非常密集的基于 ajax 的 jquery web 应用程序。它已经到了一个地步,我几乎忘记了应该触发什么动作的事件等等。
在更基本的层面上,我有点觉得我的 javascript 结构是错误的。你们如何构建 javascript/jquery 代码、事件处理等,对新手 javascript 开发人员有何建议。
【问题讨论】:
标签: javascript jquery
我正在玩弄一个非常密集的基于 ajax 的 jquery web 应用程序。它已经到了一个地步,我几乎忘记了应该触发什么动作的事件等等。
在更基本的层面上,我有点觉得我的 javascript 结构是错误的。你们如何构建 javascript/jquery 代码、事件处理等,对新手 javascript 开发人员有何建议。
【问题讨论】:
标签: javascript jquery
AMDS!
距离这个问题的第一个答案发布已经有一段时间了,很多事情都发生了变化。 首先,JS 浏览器世界似乎正朝着 AMD(异步模块定义)的代码组织方向发展。
工作方式是将所有代码编写为 AMD 模块,例如:
define('moduleName', ['dependency1', 'dependency2'], function (dependency1, dependency2) {
/*This function will get triggered only after all dependency modules loaded*/
var module = {/*whatever module object, can be any JS variable here really*/};
return module;
});
然后使用 AMD 加载器(如 curl.js 或 require.js 等)加载模块,例如:
curl(
[
'myApp/moduleA',
'myApp/moduleB'
],
).then(
function success (A, B) {
// load myApp here!
},
function failure (ex) {
alert('myApp didn't load. reason: ' + ex.message);
}
);
优点是:
您只需在页面上包含单个 <script> 元素即可加载 AMD 加载程序本身(其中一些非常小)。
之后所有的 JS 文件都会在异步 NON BLOCKING 中自动获取!时尚,因此更快!
只有在其依赖项被加载后,必要的模块才会被执行。
模块化(意味着更易于维护和重用的代码)。
如果使用得当,全局变量污染可以完全遏制。
老实说,一旦概念在您的脑海中点击,您将永远不会回到原来的方式。
P.S:从 1.7 版开始,jQuery 确实将自己注册为 AMD 模块。
有关 AMDS 的更多信息:
【讨论】:
对于 javascript 代码,我发现 Christian Heilmann 的以下链接不可或缺
我也很喜欢 Peter Michaux here 描述的方法
对于 jQuery,我衷心推荐阅读 Authoring 上的指南,我发现 jQuery plugin patterns 上的这个教程非常好
【讨论】:
为了控制我的事件,我使用了发布/订阅机制
jQuery.subscribe = function( eventName, obj, method ){
$(window).bind( eventName, function() {
obj[method].apply( obj, Array.prototype.slice.call( arguments, 1 ) );
});
return jQuery;
}
jQuery.publish = function(eventName){
$( window ).trigger( eventName, Array.prototype.slice.call( arguments, 1 ) );
return jQuery;
}
这是一个使用示例
// a couple of objects to work with
var myObj = {
method1: function( arg ) {
alert( 'myObj::method1 says: '+arg );
},
method2: function( arg1, arg2 ) {
alert( arg1 );
//republish
$.publish( 'anEventNameIMadeUp', arg2 );
}
}
var myOtherObj = {
say: function(arg){
alert('myOtherObj::say says: ' + arg);
}
}
// you can then have all your event connections in one place
//myObj::method2 is now listening for the 'start' event
$.subscribe( 'start', myObj, 'method2' );
//myOtherObj::say is now listening for the 'another' event
$.subscribe( 'anotherEvent', myOtherObj, 'say' );
//myObj::method1 is now listening for the 'anEventNameIMadeUp' event
$.subscribe( 'anEventNameIMadeUp', myObj, 'method1' );
//so is myOtherObj::say
$.subscribe( 'anEventNameIMadeUp', myOtherObj, 'say' );
// ok, trigger some events (this could happen anywhere)
$.publish( 'start', 'message1', 'message2' );
$.publish( 'anotherEvent', 'another message' );
【讨论】:
除了模块模式之外,我绝对推荐阅读对象字面量模式;这是一篇很好的文章:
【讨论】:
(function($, window, slice)
{
$.subscribe = function(eventName, obj, method)
{
$(window).bind(eventName, function()
{
obj[method].apply(obj, slice.call(arguments, 1));
});
return $;
};
$.publish = function(eventName)
{
$(window).trigger(eventName, slice.call(arguments, 1));
return jQuery;
};
})(jQuery, window, Array.prototype.slice);
【讨论】:
要添加到现有答案,这里有一个great post,其中涵盖了基于模块模式构建的更高级技术。
一旦您的 Javascript 代码达到一定大小,您将不可避免地希望通过将其分解为多个文件/模块/子模块来对其进行重构。如果您不确定如何使用模块模式来实现这一点,那么这篇文章是必读的。
【讨论】:
我的 js 文件通常遵循类似这样的命名约定:
在哪里
另外,对于 ajax,我对回调函数有一个特殊的命名约定,所以很容易分辨它们是什么。
我不确定它是否与您正在寻找的内容相近,但希望对您有所帮助。
【讨论】:
我真的很喜欢这些文章:
http://www.virgentech.com/blog/2009/10/building-object-oriented-jquery-plugin.html
http://stefangabos.ro/jquery/jquery-plugin-boilerplate-revisited/
他们帮助我了解 Telerik 如何为 asp.net mvc 创建扩展。
【讨论】:
我喜欢 AMD 的想法(请参阅 nix's answer)。
但我通常会将所有 JS 文件编译成一个 JS 文件。 在这种情况下,不需要异步部分。所以我写了一个小“Infile Module Loader”。
这里是:https://codereview.stackexchange.com/questions/14530/a-little-infile-amd
【讨论】:
我们可以在我们的 javascript-jquery 应用程序中使用 mvc 模式。 (Backbone.js、knockout.js vs....)是我们可以用来实现这一目标的成熟库。
【讨论】: