Hug*_*are 561 javascript architecture formatting jquery design-patterns
随着像jQuery这样的JavaScript框架使客户端Web应用程序更丰富,更实用,我开始注意到一个问题......
你是如何保持这种组织的?
我提到了jQuery,但它实际上是任何JavaScript代码.我发现随着线条开始堆积起来,管理脚本文件或找到你要找的东西变得更加困难.我发现最大的问题可能是有很多方法可以做同样的事情,很难知道哪一个是目前普遍接受的最佳实践.
是否有关于保持.js文件与应用程序其余部分一样美观和整洁的最佳方法的一般建议?或者这仅仅是IDE的问题?那里有更好的选择吗?
编辑
这个问题旨在更多地关注代码组织而不是文件组织.有一些非常好的合并文件或分割内容的例子.
我的问题是:目前普遍接受的组织实际代码的最佳实践方法是什么?您的方式是什么,甚至是推荐的方式与页面元素交互并创建可互相冲突的可重用代码?
有些人列出了名称空间,这是一个好主意.还有什么其他方法,更具体地说是处理页面上的元素并保持代码整洁有序?
pol*_*ear 183
这将是更好的很多,如果JavaScript的已建成的命名空间,但我觉得像达斯汀·迪亚兹整理东西描述在这里帮助我很多.
var DED = (function() {
var private_var;
function private_method()
{
// do stuff here
}
return {
method_1 : function()
{
// do stuff here
},
method_2 : function()
{
// do stuff here
}
};
})();
Run Code Online (Sandbox Code Playgroud)
我将不同的"命名空间"和有时候的单个类放在不同的文件中.通常我从一个文件开始,并且作为一个类或命名空间变得足够大以保证它,我将它分成它自己的文件.使用工具将所有文件组合起来进行制作也是一个很好的主意.
Jas*_*ore 88
我尽量避免在HTML中加入任何javascript.所有代码都封装在类中,每个类都在自己的文件中.对于开发,我有单独的<script>标记来包含每个js文件,但是它们会合并到一个更大的包中进行生产,以减少HTTP请求的开销.
通常,我会为每个应用程序提供一个"main"js文件.所以,如果我正在编写一个"调查"应用程序,我会有一个名为"survey.js"的js文件.这将包含jQuery代码的入口点.我在实例化期间创建jQuery引用,然后将它们作为参数传递给我的对象.这意味着javascript类是"纯粹的",并且不包含对CSS ID或类名的任何引用.
// file: survey.js
$(document).ready(function() {
var jS = $('#surveycontainer');
var jB = $('#dimscreencontainer');
var d = new DimScreen({container: jB});
var s = new Survey({container: jS, DimScreen: d});
s.show();
});
Run Code Online (Sandbox Code Playgroud)
我还发现命名约定对于可读性很重要.例如:我在所有jQuery实例之前加上'j'.
在上面的示例中,有一个名为DimScreen的类.(假设这会使屏幕变暗并弹出一个警告框.)它需要一个div元素,它可以放大以覆盖屏幕,然后添加一个警告框,所以我传入一个jQuery对象.jQuery有一个插件概念,但似乎有限(例如实例不是持久性的,无法访问),没有真正的好处.所以DimScreen类将是一个标准的javascript类,恰好使用jQuery.
// file: dimscreen.js
function DimScreen(opts) {
this.jB = opts.container;
// ...
}; // need the semi-colon for minimizing!
DimScreen.prototype.draw = function(msg) {
var me = this;
me.jB.addClass('fullscreen').append('<div>'+msg+'</div>');
//...
};
Run Code Online (Sandbox Code Playgroud)
我使用这种方法构建了一些相当复杂的应用程序.
Gre*_*reg 39
您可以将脚本拆分为单独的文件进行开发,然后创建一个"发布"版本,将所有文件一起填入并运行YUI Compressor或其类似的东西.
Dam*_*kić 27
通过我做的一份较早的帖子的启发Rake文件和供应商分布式目录WysiHat(一RTE通过更改日志中提到),并做了一些修改,包括代码检查与JSLint的和缩小与锐压缩机.
我们的想法是使用链轮(从WysiHat)来分发之前多的JavaScript与锐压缩机合并成一个文件,请与JSLint的合并文件的语法,然后再缩小它.
先决条件
现在做
现在在JavaScript项目的根目录中创建一个名为"Rakefile"的文件,并将以下内容添加到其中:
require 'rake'
ROOT = File.expand_path(File.dirname(__FILE__))
OUTPUT_MERGED = "final.js"
OUTPUT_MINIFIED = "final.min.js"
task :default => :check
desc "Merges the JavaScript sources."
task :merge do
require File.join(ROOT, "vendor", "sprockets")
environment = Sprockets::Environment.new(".")
preprocessor = Sprockets::Preprocessor.new(environment)
%w(main.js).each do |filename|
pathname = environment.find(filename)
preprocessor.require(pathname.source_file)
end
output = preprocessor.output_file
File.open(File.join(ROOT, OUTPUT_MERGED), 'w') { |f| f.write(output) }
end
desc "Check the JavaScript source with JSLint."
task :check => [:merge] do
jslint_path = File.join(ROOT, "vendor", "jslint.js")
sh 'java', 'org.mozilla.javascript.tools.shell.Main',
jslint_path, OUTPUT_MERGED
end
desc "Minifies the JavaScript source."
task :minify => [:merge] do
sh 'java', 'com.yahoo.platform.yui.compressor.Bootstrap', '-v',
OUTPUT_MERGED, '-o', OUTPUT_MINIFIED
end
Run Code Online (Sandbox Code Playgroud)
如果您已正确完成所有操作,则应该能够在控制台中使用以下命令:
rake merge
- 将不同的JavaScript文件合并为一个rake check
- 检查代码的语法(这是默认任务,所以你只需键入rake
)rake minify
- 准备JS代码的缩小版本关于源合并
使用Sprockets,JavaScript预处理器可以包含(或require
)其他JavaScript文件.使用以下语法来包含初始文件中的其他脚本(名为"main.js",但您可以在Rakefile中更改它):
(function() {
//= require "subdir/jsfile.js"
//= require "anotherfile.js"
// some code that depends on included files
// note that all included files can be in the same private scope
})();
Run Code Online (Sandbox Code Playgroud)
然后...
看看WysiHat提供的Rakefile来设置自动化单元测试.好东西 :)
现在回答
这不能很好地回答原始问题.我知道并且对此感到抱歉,但是我在这里发布了它,因为我希望其他人可以组织他们的混乱.
我解决这个问题的方法是尽可能多地进行面向对象的建模,并将实现分成不同的文件.然后处理程序应尽可能短.List
单身的例子也很好.
和名称空间......他们可以通过更深层次的对象结构来模仿.
if (typeof org === 'undefined') {
var org = {};
}
if (!org.hasOwnProperty('example')) {
org.example = {};
}
org.example.AnotherObject = function () {
// constructor body
};
Run Code Online (Sandbox Code Playgroud)
我不是模仿的忠实粉丝,但如果您有许多想要移出全球范围的物品,这可能会有所帮助.
Ner*_* Jr 18
代码组织要求采用约定和文档标准:
1.物理文件的命名空间代码;
Exc = {};
Run Code Online (Sandbox Code Playgroud)
2.这些命名空间中的组类javascript;
3.设置用于表示现实世界对象的原型或相关函数或类;
Exc = {};
Exc.ui = {};
Exc.ui.maskedInput = function (mask) {
this.mask = mask;
...
};
Exc.ui.domTips = function (dom, tips) {
this.dom = gift;
this.tips = tips;
...
};
Run Code Online (Sandbox Code Playgroud)
4.设置约定以改进代码.例如,将其所有内部函数或方法分组到对象类型的类属性中.
Exc.ui.domTips = function (dom, tips) {
this.dom = gift;
this.tips = tips;
this.internal = {
widthEstimates: function (tips) {
...
}
formatTips: function () {
...
}
};
...
};
Run Code Online (Sandbox Code Playgroud)
5.制作名称空间,类,方法和变量的文档.必要时还讨论一些代码(一些FI和Fors,它们通常实现代码的重要逻辑).
/**
* Namespace <i> Example </i> created to group other namespaces of the "Example".
*/
Exc = {};
/**
* Namespace <i> ui </i> created with the aim of grouping namespaces user interface.
*/
Exc.ui = {};
/**
* Class <i> maskdInput </i> used to add an input HTML formatting capabilities and validation of data and information.
* @ Param {String} mask - mask validation of input data.
*/
Exc.ui.maskedInput = function (mask) {
this.mask = mask;
...
};
/**
* Class <i> domTips </i> used to add an HTML element the ability to present tips and information about its function or rule input etc..
* @ Param {String} id - id of the HTML element.
* @ Param {String} tips - tips on the element that will appear when the mouse is over the element whose identifier is id <i> </i>.
*/
Exc.ui.domTips = function (id, tips) {
this.domID = id;
this.tips = tips;
...
};
Run Code Online (Sandbox Code Playgroud)
这些只是一些提示,但这对组织代码有很大帮助.记住你必须有纪律才能成功!
meo*_*ouw 13
遵循良好的OO设计原则和设计模式对于使代码易于维护和理解有很长的路要走.但我最近发现的最好的事情之一是信号和插槽,即发布/订阅. 有关简单的jQuery实现,请查看http://markdotmeyer.blogspot.com/2008/09/jquery-publish-subscribe.html.
这个想法很好地用于其他语言的GUI开发.当代码中某处发生重要事件时,您会发布一个全局合成事件,其他对象中的其他方法可能会订阅该事件.这样可以很好地分离物体.
我认为Dojo(和Prototype?)有这种技术的内置版本.
另请参阅什么是信号和插槽?
Eug*_*kin 11
Dojo从第一天就开始使用模块系统.事实上,它被认为是Dojo的基石,它是将所有这些组合在一起的胶水:
使用模块Dojo实现以下目标:
dojo.declare()
)的命名空间- 不污染全局空间,与其他库共存,以及用户的非Dojo感知代码.dojo.require()
)同步或异步加载模块.我的老板仍然谈到他们编写模块化代码(C语言)的时代,并抱怨现在的代码有多糟糕!据说程序员可以在任何框架中编写程序集.始终存在一种克服代码组织的策略.基本问题在于将java脚本视为玩具并且从不尝试学习它的人.
在我的例子中,我使用适当的init_screen()在UI主题或应用程序屏幕上编写js文件.使用正确的id命名约定,我确保根元素级别没有名称空间冲突.在不引人注目的window.load()中,我根据顶级id绑定了一些东西.
我严格使用java脚本闭包和模式来隐藏所有私有方法.执行此操作后,从未遇到过冲突的属性/函数定义/变量定义的问题.但是,与团队合作时,通常很难强制执行相同的严格要求.
查看JavasciptMVC.
您可以 :
将代码拆分为模型,视图和控制器层.
将所有代码压缩到单个生产文件中
自动生成代码
创建并运行单元测试
还有更多......
最重要的是,它使用jQuery,因此您也可以利用其他jQuery插件.
我很惊讶没人提到MVC框架.我一直在使用Backbone.js模块化和解耦我的代码,这是非常宝贵的.
这里有很多这样的框架,其中大多数都非常小.我的个人意见是,如果您要编写的不仅仅是几行jQuery用于华而不实的UI,或者想要一个丰富的Ajax应用程序,MVC框架将使您的生活更轻松.
"写得像疯了似的,只希望它能做到最好?",我看到这样的项目是由2位开发人员开发和维护的,这是一个包含大量JavaScript代码的庞大应用程序.最重要的是,您可以想到的每个可能的jquery函数都有不同的快捷方式.我建议他们将代码组织为插件,因为它是类,模块,命名空间和整个Universe的jquery等价物.但事情变得更糟,现在他们开始编写插件来替换项目中使用的3行代码的每个组合.Personaly我认为jQuery是魔鬼,它不应该用于有大量JavaScript的项目,因为它鼓励你懒惰而不考虑以任何方式组织代码.我宁愿阅读100行javascript而不是一行有40个链式jQuery函数(我' 不开玩笑).与流行的看法相反,将javascript代码组织成名称空间和类的等价物非常容易.这就是YUI和Dojo所做的.如果你愿意,你可以轻松自己动手.我觉得YUI的方法更好,更有效率.但是,如果你想编写任何有用的东西,你通常需要一个支持片段的好编辑器来补偿YUI命名约定.
我为我不需要在屏幕上多次实例化的每一件事创建单身,其他一切都是类.并且所有这些都放在同一文件中的相同名称空间中.所有内容都经过评论,并使用UML状态图进行设计.javascript代码没有html,所以没有内联javascript,我倾向于使用jquery来最小化跨浏览器问题.
在我的上一个项目-Viajeros.com-我使用了几种技术的组合.我不知道如何组织一个网络应用程序 - Viajeros是一个社交网站,适合那些定义明确的部分的旅行者,所以很容易将每个区域的代码分开.
我根据站点部分使用名称空间模拟和模块的延迟加载.在每个页面加载时,我声明一个"vjr"对象,并始终为它加载一组公共函数(vjr.base.js).然后每个HTML页面通过简单的方式决定需要哪些模块:
vjr.Required = ["vjr.gallery", "vjr.comments", "vjr.favorites"];
Run Code Online (Sandbox Code Playgroud)
Vjr.base.js从服务器中获取每一个并执行它们.
vjr.include(vjr.Required);
vjr.include = function(moduleList) {
if (!moduleList) return false;
for (var i = 0; i < moduleList.length; i++) {
if (moduleList[i]) {
$.ajax({
type: "GET", url: vjr.module2fileName(moduleList[i]), dataType: "script"
});
}
}
};
Run Code Online (Sandbox Code Playgroud)
每个"模块"都有这种结构:
vjr.comments = {}
vjr.comments.submitComment = function() { // do stuff }
vjr.comments.validateComment = function() { // do stuff }
// Handlers
vjr.comments.setUpUI = function() {
// Assign handlers to screen elements
}
vjr.comments.init = function () {
// initialize stuff
vjr.comments.setUpUI();
}
$(document).ready(vjr.comments.init);
Run Code Online (Sandbox Code Playgroud)
鉴于我有限的Javascript知识,我知道必须有更好的方法来管理它,但直到现在它对我们来说都很有用.
小智 6
以Jquery为中心的NameSpace方式组织代码可能如下所示......并且不会与其他Javascript API(如Prototype,Ext)发生冲突.
<script src="jquery/1.3.2/jquery.js" type="text/javascript"></script>
<script type="text/javascript">
var AcmeJQ = jQuery.noConflict(true);
var Acme = {fn: function(){}};
(function($){
Acme.sayHi = function()
{
console.log('Hello');
};
Acme.sayBye = function()
{
console.log('Good Bye');
};
})(AcmeJQ);
// Usage
// Acme.sayHi();
// or
// <a href="#" onclick="Acme.sayHi();">Say Hello</a>
</script>
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助.
OO + MVC的优秀校长肯定会在管理复杂的JavaScript应用程序方面走得很远.
基本上我正在组织我的应用程序和javascript到以下熟悉的设计(从我的桌面编程时代到Web 2.0一直存在)
图像上数值的说明:
在过去,我会将文件分成自己的js,并使用通常的做法在Javascript中创建OO原则.我很快发现有很多方法可以编写JS OO并且并不一定所有团队成员都采用相同的方法.随着团队变得更大(在我的情况下超过15人),这变得复杂,因为没有标准的面向对象的Javascript方法.与此同时,我不想写自己的框架,并重复一些我确信比我解决的人更聪明的工作.
jQuery是非常好的Javascript Framework,我喜欢它,但随着项目变得越来越大,我显然需要我的Web应用程序的额外结构,特别是为了促进标准化OO实践.对于我自己,经过几次实验,我发现YUI3 Base和Widget(http://yuilibrary.com/yui/docs/widget/和http://yuilibrary.com/yui/docs/base/index.html)基础设施提供了正是我需要的.我使用它们的理由很少.
与许多观点相反,我不一定要在jQuery和YUI3之间做出选择.这两者可以和平共处.虽然YUI3为我的复杂Web应用程序提供了必要的OO模板,但jQuery仍然为我的团队提供了易于使用的JS抽象,我们都喜欢和熟悉它们.
使用YUI3,我已经设法通过分离扩展Base作为Model的类来创建MVC模式,将Widget扩展为View的类,当然你有Controller类进行必要的逻辑和服务器端调用.
Widget可以使用基于事件的模型相互通信,并根据预定义的界面监听事件并执行必要的任务.简单地说,将OO + MVC结构放到JS中对我来说是一种快乐.
只是免责声明,我不为雅虎工作!而且只是一个试图解决原始问题所提出的同一问题的建筑师.我想如果有人发现等效的OO框架,这也可以.原则上,这个问题也适用于其他技术.感谢所有提出OO Principles + MVC的人,让我们的编程日更易于管理.
我使用Dojo的包管理(dojo.require
和dojo.provide
)和类系统(dojo.declare
也允许简单的多重继承)将我的所有类/小部件模块化为单独的文件.这不仅可以使您的代码保持井井有条,而且还可以让您懒惰/及时加载类/小部件.
归档时间: |
|
查看次数: |
48068 次 |
最近记录: |