组织的jQuery / JavaScript的code最好的办法(2013年) [英] Best way to organize jQuery/JavaScript code (2013)

查看:109
本文介绍了组织的jQuery / JavaScript的code最好的办法(2013年)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个答案之前已经回答了,但老不是最新的。我有一个单一的文件超过2000行code,而且大家都知道这是不好的做法,尤其是当我翻翻code或增加新的功能。我想更好地组织我的code,现在和未来。

This answer has been answered before but are old and not up to date. I have over 2000 lines of code in a single file, and as we all know this is bad practice, especially when i'm looking through code or adding new features. I want to better organize my code, for now and for the future.

我要指出,我要建有很多按钮,用户界面​​元素,拖,滴,动作监听器/处理器和功能在全球范围内,几个听众可以使用相同的功能的工具(而不是一个简单的网站)。

I should mention that I'm building a tool (not a simple website) with lots of buttons, UI elements, drag, drops, action listeners/handlers and function in the global scope where several listeners may use the same function.

$('#button1').on('click', function(e){
    // Determined action.
    update_html();
});

... // Around 75 more of this

function update_html(){ .... }

...

更多例如code

我真的需要这个组织code为尽其用,不要重复自己,并能够添加新的功能和更新旧的。我将在这个由我自己来工作。有些选择可能是100线$​​ C $ C其他的都1.我已经看过了一下在 require.js ,发现它有点重复了,居然写更多$ C $温度比需要的。我接受符合这一标准,并链接到任何资源的可能的解决方案/例子始终是一个加号。

I really need to organize this code for best use and not to repeat myself and be able to add new features and update old ones. I will be working on this by myself. Some selectors can be 100 lines of code others are 1. I have looked a bit at require.js and found it kinda repetitive, and actually writing more code than needed . I'm open to any possible solution that fit this criteria and link to resource / examples are always a plus.

感谢。

推荐答案

我去了一些简单的东西,可能或可能不会,帮你。有些人可能会很明显,有些人可能是非常神秘的。

I'll go over some simple things that may, or may not, help you. Some might be obvious, some might be extremely arcane.

您分离code成多个模块单元是一个很好的第一步。农达是什么在起作用在一起,并把他们在自己的小钢骨单位。不用担心格式现在,保持它内联。该结构是后的点。

Separating your code into multiple, modular units is a very good first step. Round up what works "together" and put them in their own little encased unit. don't worry about the format for now, keep it inline. The structure is a later point.

那么,假设你有一个页面是这样的:

So, suppose you have a page like this:

有将是有意义的划分,使得所有的头相关的事件处理程序/粘合剂是在那里,易于维护的(和不具有通过1000线进行筛选)。

It would make sense to compartmentalize so that all the header-related event handlers/binders are in there, for ease of maintenance (and not having to sift through 1000 lines).

您可以再使用的工具,如步兵重新建立你的JS回单单元。

You can then use a tool such as Grunt to re-build your JS back to a single unit.

使用的库如RequireJS或CommonJS的实施所谓的 AMD 。异步加载模块可以让你明确地说出你的$ C $,c取决于,然后让你卸载库调用到code。你可以只从字面上说,这需要jQuery的,而AMD将加载它,并执行code 当jQuery是可用

Use a library such as RequireJS or CommonJS to implement something called AMD. Asynchronous Module Loading allows you to explicitely state what your code depends on, which then allows you to offload the library-calling to the code. You can just literally say "This needs jQuery" and the AMD will load it, and execute your code when jQuery is available.

这也有一个隐藏的宝石:该库加载将完成第二个DOM就绪,而不是之前。这不再停止你的页面加载了!

This also has a hidden gem: the library loading will be done the second the DOM is ready, not before. This no longer halts load-up of your page!

请参阅线框?我有两个广告单元。他们将最有可能有共同的事件侦听器。

See the wireframe? I have two ad units. They'll most likely have shared event listeners.

您在这一步的任务就是找出重复的点在code和尝试合成到模块这一切。模块,现在,将包含一切。当我们走,我们会分开的东西。

Your task in this step is to identify the points of repetition in your code and to try to synthesise all this into modules. Modules, right now, will encompass everything. We'll split stuff as we go along.

这一步的整体思路是从第1步走,并删除所有复制面食,用松散耦合的单位来取代它们。这样,代替具有:

The whole idea of this step is to go from step 1 and delete all the copy-pastas, to replace them with units that are loosely coupled. So, instead of having:

ad_unit1.js

 $("#au1").click(function() { ... });

ad_unit2.js

 $("#au2").click(function() { ... });

我将有:

ad_unit.js

 var AdUnit = function(elem) {
     this.element = elem || new jQuery();
 }
 AdUnit.prototype.bindEvents = function() {
     ... Events go here
 }

page.js

 var AUs = new AdUnit($("#au1,#au2"));
 AUs.bindEvents();

允许你除了摆脱重复您的事件之间划分并您的标记。这是一个pretty体面的一步,我们将进一步后来扩展这个。

Which allows you to compartmentalize between your events and your markup in addition to getting rid of repetition. This is a pretty decent step and we'll extend this further later on.

如果您想模块化,减少重复更进一步,还有一堆围绕实现MVC真棒框架(模型 - 视图 - 控制器)的方法。我最喜欢的是骨干/脊柱,然而,也有棱角,Yii的,......这样的例子不胜枚举。

If you'd like to modularize and reduce repetitions even further, there are a bunch of awesome frameworks around that implement MVC (Model - View - Controller) approaches. My favourite is Backbone/Spine, however, there's also Angular, Yii, ... The list goes on.

A 型号重新presents您的数据。

A Model represents your data.

A 查看重新presents您的标记和与之相关的所有事件

A View represents your mark-up and all the events associated to it

A 控制器重新presents你的业务逻辑 - 换句话说,控制器告诉页面加载什么看法和使用什么型号

A Controller represents your business logic - in other words, the controller tells the page what views to load and what models to use.

这将是一个显著学习的第一步,但奖品是值得的:在它有利于意大利面清洁,模块化code

This will be a significant learning step, but the prize is worth it: it favours clean, modular code over spaghetti.

有很多其他的事情可以做,这些都只是指导方针和思路。

There are plenty of other things you can do, those are just guidelines and ideas.

下面是你的code一些具体的改进:

Here are some specific improvements to your code:

 $('.new_layer').click(function(){

    dialog("Create new layer","Enter your layer name","_input", {

            'OK' : function(){

                    var reply = $('.dialog_input').val();

                    if( reply != null && reply != "" ){

                            var name = "ln_"+reply.split(' ').join('_');
                            var parent = "";

                            if(selected_folder != "" ){
                            parent = selected_folder+" .content";
                            }

                            $R.find(".layer").clone()
                            .addClass(name).html(reply)
                            .appendTo("#layer_groups "+parent);

                            $R.find(".layers_group").clone()
                            .addClass(name).appendTo('#canvas '+selected_folder);

            }

        }

    });
 });

这是更好的写法如下:

$("body").on("click",".new_layer", function() {
    dialog("Create new layer", "Enter your layer name", "_input", {
         OK: function() {
             // There must be a way to get the input from here using this, if it is a standard library. If you wrote your own, make the value retrievable using something other than a class selector (horrible performance + scoping +multiple instance issues)

             // This is where the view comes into play. Instead of cloning, bind the rendering into a JS prototype, and instantiate it. It means that you only have to modify stuff in one place, you don't risk cloning events with it, and you can test your Layer stand-alone
             var newLayer = new Layer();
             newLayer
               .setName(name)
               .bindToGroup(parent);
          }
     });
});

在code早些时候:

Earlier in your code:

window.Layer = function() {
    this.instance = $("<div>");
    // Markup generated here
};
window.Layer.prototype = {
   setName: function(newName) {
   },
   bindToGroup: function(parentNode) {
   }
}

突然,你有没有办法复制粘贴来创建你的code的任何地方标准层。你在五个不同的地方这样做。我刚刚救你五复制焊膏。

Suddenly, you have a way to create a standard layer from anywhere in your code without copy pasting. You're doing this in five different places. I've just saved you five copy-pastes.

还有一个:

//规则集包装的行动

// Ruleset wrapper for actions

var PageElements = function(ruleSet) {
ruleSet = ruleSet || [];
this.rules = [];
for (var i = 0; i < ruleSet.length; i++) {
    if (ruleSet[i].target && ruleSet[i].action) {
        this.rules.push(ruleSet[i]);
    }
}
}
PageElements.prototype.run = function(elem) {
for (var i = 0; i < this.rules.length; i++) {
    this.rules[i].action.apply(elem.find(this.rules.target));
}
}

var GlobalRules = new PageElements([
{
    "target": ".draggable",
    "action": function() { this.draggable({
        cancel: "div#scrolling, .content",
        containment: "document"
        });
    }
},
{
    "target" :".resizable",
    "action": function() {
        this.resizable({
            handles: "all",
            zIndex: 0,
            containment: "document"
        });
    }
}

]);

GlobalRules.run($("body"));

// If you need to add elements later on, you can just call GlobalRules.run(yourNewElement);

这是,如果你有不属于标准的事件,或创建事件登记规则非常有效的方式。这也是当与发布/订阅通知系统相结合,当绑定到一个事件你火,只要你创建元素认真踢屁股。 Fire'n'forget模块化事件绑定!

This is a very potent way to register rules if you have events that are not standard, or creation events. This is also seriously kick-ass when combined with a pub/sub notification system and when bound to an event you fire whenever you create elements. Fire'n'forget modular event binding!

这篇关于组织的jQuery / JavaScript的code最好的办法(2013年)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆