JavaScript'te kod organizasyonu hakkında yaygın olarak kabul edilen en iyi uygulamalar [kapalı]


561

JQuery gibi JavaScript çerçeveleri istemci tarafı web uygulamalarını daha zengin ve daha işlevsel hale getirdiğinden, bir sorunu fark etmeye başladım ...

Dünyada bunu nasıl düzenli tutuyorsunuz?

  • Tüm işleyicilerinizi tek bir noktaya koyun ve tüm olaylar için fonksiyonlar yazın.
  • Tüm işlevselliklerinizi sarmak için işlev / sınıflar mı oluşturuyorsunuz?
  • Deli gibi yaz ve sadece en iyisi için çalışıyor umuyoruz?
  • Vazgeç ve yeni bir kariyer sahibi misin?

JQuery'den bahsediyorum, ama genel olarak herhangi bir JavaScript kodu. Satırlardaki satırlar birikmeye başladığında, komut dosyalarını yönetmek veya aradığınızı bulmak zorlaşıyor. Muhtemelen bulduğum en büyük problemler aynı şeyi yapmanın pek çok yolu var, hangisinin şu anda yaygın olarak kabul edilen en iyi uygulama olduğunu bilmek zor.

.Js dosyalarınızı uygulamanızın geri kalanı kadar güzel ve düzenli tutmanın en iyi yolu hakkında genel öneriler var mı? Yoksa bu sadece bir IDE meselesi mi? Dışarıda daha iyi bir seçenek var mı?


DÜZENLE

Bu sorunun daha çok dosya organizasyonu değil kod organizasyonu hakkında olması amaçlanmıştır. Dosyaları birleştirmek veya içeriği bölmek için gerçekten iyi örnekler var.

Sorum şu: gerçek kodunuzu düzenlemenin yaygın olarak kabul edilen en iyi uygulama yolu nedir? Yolunuz ve hatta sayfa öğeleriyle etkileşim kurmanın ve birbiriyle çakışmayan tekrar kullanılabilir kodlar oluşturmanın önerilen bir yolu nedir?

Bazı insanlar iyi bir fikir olan ad alanlarını listelemişlerdir . Sayfadaki öğelerle daha fazla ilgilenmek ve kodu düzenli ve düzenli tutmak için başka yollar nelerdir?


kod dosyalarının kendisi hakkında konuşmak için zaman ayıran biri, JS dosyalarını birleştirmek ve sıkıştırmak için kullandığı aracı "sadece" değil: stackoverflow.com/questions/16736483/…
Adrien

Yanıtlar:


183

Javascript inşa ad alanları olsaydı çok daha güzel olurdu, ama Dustin Diaz açıklar gibi ben organize şeyler bulmak burada bana çok yardımcı oluyor.

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
            }
    };
})();

Ayrı dosyalara farklı "ad alanları" ve bazen de bireysel sınıflar koydum. Genellikle bir dosya ile başlıyorum ve bir sınıf veya ad alanı onu garanti edecek kadar büyük hale geldikçe, kendi dosyasına ayırıyorum. Üretim için tüm dosyalarınızı birleştirmek için bir araç kullanmak da mükemmel bir fikirdir.


24
Genellikle "crockford yolu" olarak adlandırıyorum. Benden +1
Matt Briggs

4
Hatta biraz daha ileri gidebilirsiniz. Bu bağlantıya bakın: wait-till-i.com/2007/08/22/…
MKroehnert

4
@MattBriggs aksi takdirde denir module patternve dayanmaktadır IIFE pattern.
Adrien Be

Sınıfları bir şekilde dışa aktarmanıza gerek yok mu? Böyle bir modülün dışından bir nesne nasıl oluşturulur? Veya createNewSomething()dönüş nesnesinde bir yöntem olmalı , bu nedenle nesne oluşturma yalnızca modül içinde gerçekleşir mi? Hm ... Sınıfların (kurucuların) dışarıdan görünür olmasını beklerdim.
robsch

@robsch Örneği herhangi bir parametre almaz, ancak çoğu alır. Bunun genellikle nasıl yapıldığına ilişkin örneğime bakın (TypeScript, ancak% 99 aynı): repl.it/@fatso83/Module-Pattern-in-TypeScript
oligofren

88

HTML ile herhangi bir javascript dahil kaçınmaya çalışın. Tüm kod sınıflara eklenir ve her sınıf kendi dosyasındadır. Geliştirme için, her bir js dosyasını içerecek ayrı <script> etiketleri var, ancak HTTP isteklerinin yükünü azaltmak için üretim için tek bir daha büyük pakette birleştiriliyorlar.

Genellikle, her uygulama için tek bir 'ana' js dosyası olacak. Yani, bir "anket" uygulaması yazıyordu, ben "survey.js" adlı bir js dosyası olurdu. Bu, jQuery koduna giriş noktasını içerir. Örnekleme sırasında jQuery başvuruları oluşturur ve bunları nesnelerim olarak parametre olarak iletirim. Bu, javascript sınıflarının 'saf' olduğu ve CSS kimliklerine veya sınıf adlarına herhangi bir referans içermediği anlamına gelir.

// 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();
});

Ayrıca adlandırma kuralının okunabilirlik açısından önemli olduğunu düşünüyorum. Örneğin: Tüm jQuery örneklerine 'j' başlıyorum.

Yukarıdaki örnekte DimScreen adında bir sınıf var. (Bunun ekranı kararttığını ve bir uyarı kutusu açtığını varsayın.) Ekranı kaplayacak şekilde büyütülebilen bir div öğesine ihtiyaç duyuyor ve ardından bir uyarı kutusu ekliyorum, bu yüzden bir jQuery nesnesine geçiyorum. jQuery bir eklenti kavramına sahiptir, ancak gerçek bir tersi olmadan sınırlayıcı görünüyordu (örn. örnekler kalıcı değildir ve erişilemez). Bu yüzden DimScreen sınıfı, sadece jQuery kullanan standart bir javascript sınıfı olacaktır.

// 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>');
  //...
};

Bu yaklaşımı kullanarak oldukça karmaşık uygulamalar yaptım.


15
$Değişken adı öneki olarak kullanmanın daha yaygın bir uygulama olduğunu düşünüyorum, ancak yanlış olabilirim. Yani, $s = $('...')bunun yerine jS = $('...'), sadece bir tercih meselesi sanırım. İlginçtir, çünkü Macarca gösterimin kod kokusu olduğu düşünülmektedir. JavaScript kod kurallarının / tercihlerimin bazılarının C # / Java kodlama kurallarımdan ne kadar farklı olması garip.
jamiebarrow

9
@jamie Bu durumda bir kod kokusu değil, tam olarak Macarca'nın iyi olduğu birkaç durumdan biri . Sen okumak isteyebilirsiniz bu .
Dan Abramov

3
@ DanAbramov bağlantı için teşekkür ederim. Joel'in tüm bloglarını gerçekten okumalıyım, o kadar iyi anlatıyor. Kesinlikle sahip olduğu şöhreti / şöhreti hak ediyor. Ben sevk edecektir Systems Hungarianbir kod koku olarak ve Apps Hungarianbundan :) Bir uygulama olarak
jamiebarrow

Sanırım C # dünyasında var, şimdi düşünüyorum , kullanımını teşvik etmek için harika bir makale olabilir . Kullanıma karşı argümanların çoğu var, döndürülen şeyin 'türünden' emin olamayacağınız yerdir, ancak sanırım argüman, döndürülen şeyin 'sınıfını' bilmemeye karşı olmalıdır. Apps Macarca kullanıyorsanız, bu endişe olmamalı ... ilginç.
jamiebarrow

3
@Marnen: Ne demek istediğini anlıyorum, ama programcı için bir rehber olarak işe yaramaz. $ Öneki daha sonra kodumu okurken ne olduğunu hatırlatıyor ve böylece daha hızlı anlama yardımcı olur.
Sean

39

Komut dosyalarınızı geliştirme için ayrı dosyalara bölebilir, ardından hepsini bir araya getirip YUI Kompresörü veya buna benzer bir şey çalıştıracağınız bir "sürüm" sürümü oluşturabilirsiniz .


Bazen gereksiz javascript komut dosyaları vardır. Bunları müşteriye göndermek israftır. Bence sadece gerekli olanı göndermenin yanında. Elbette, intranet uygulaması gibi gün boyu kullanılan bir web uygulaması için, tüm toplu işi ilk sayfa yüklemesinde bir kerede göndermek daha iyi olabilir.
DOK

2
@DOK derlemesi kullanılmayan şeylerin eksizyonunu içermelidir.
aehlke

Ayrıca, ilk sayfayı yüklediğiniz ve daha sonra gerekli komut dosyalarının zaman uyumsuz yüklemesini gerçekleştirdiğiniz (bu sorunun diğer yanıtlarında belirtildiği gibi) bant genişliği gereksinimlerini denemek ve azaltmak için tembel yükleme kavramı da vardır. Yine de, bu daha fazla istek gerektirebilir ve aslında daha az kullanılabilir olabilir. @DOK, JS önbelleğe alınırsa, bir orta düzey istek birkaç küçük istekten daha iyi olabilir.
jamiebarrow

27

Daha önceki yayınlardan esinlenerek WysiHat (changelog tarafından bahsedilen bir RTE) ile dağıtılan Rakefile ve satıcı dizinlerinin bir kopyasını yaptım ve JSLint ile kod kontrolünü ve YUI Kompresörü ile küçültmeyi içeren birkaç değişiklik yaptım .

Fikir, birden fazla JavaScripts'i tek bir dosyada birleştirmek için Sprockets (WysiHat'tan) kullanmak, birleştirilmiş dosyanın JSLint ile sözdizimini kontrol etmek ve dağıtımdan önce YUI Kompresörü ile küçültmektir.

Ön şartlar

  • Java Çalışma Zamanı
  • yakut ve komisyon mücevher
  • Sınıf yoluna nasıl bir JAR koyacağınızı bilmelisiniz

Şimdi yap

  1. Rhino'yu indir ve sınıf yoluna JAR ("js.jar") koy
  2. YUI Kompresörünü indirin ve JAR'ı (build / yuicompressor-xyz.jar) sınıf yolunuza koyun
  3. WysiHat'ı indirin ve "vendor" dizinini JavaScript projenizin kök dizinine kopyalayın
  4. Rhino için JSLint'i indirin ve "satıcı" dizinine koyun

Şimdi JavaScript projesinin kök dizininde "Rakefile" adlı bir dosya oluşturun ve bu dosyaya aşağıdaki içeriği ekleyin:

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

Her şeyi doğru bir şekilde yaptıysanız, konsolunuzda aşağıdaki komutları kullanabilmeniz gerekir:

  • rake merge - farklı JavaScript dosyalarını tek bir dosyada birleştirmek için
  • rake check- kodunuzun sözdizimini kontrol etmek için (bu varsayılan görevdir, böylece yazabilirsiniz rake)
  • rake minify - JS kodunuzun küçültülmüş bir versiyonunu hazırlamak için

Kaynak birleştirmede

Sprockets kullanarak, requirediğer JavaScript dosyalarını ekleyebileceğiniz (veya ) JavaScript ön işlemcisi . İlk dosyadaki diğer komut dosyalarını ("main.js" olarak adlandırılır) eklemek için aşağıdaki sözdizimini kullanın, ancak bunu Rakefile'da değiştirebilirsiniz:

(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
})();

Ve sonra...

Otomatik birim testini ayarlamak için WysiHat ile sağlanan Rakefile'a göz atın. Güzel iş :)

Ve şimdi cevap için

Bu orijinal soruyu çok iyi cevaplamıyor. Biliyorum ve bunun için üzgünüm, ama buraya gönderdim çünkü umarım birilerinin karışıklıklarını düzenlemesi yararlı olabilir.

Soruna yaklaşımım, yapabildiğim kadar nesne yönelimli modelleme yapmak ve uygulamaları farklı dosyalara ayırmaktır. Ardından işleyiciler mümkün olduğunca kısa olmalıdır. ListSingleton ile örnek de güzel bir örnek.

Ve isim alanları ... daha derin nesne yapısı ile taklit edilebilirler.

if (typeof org === 'undefined') {
    var org = {};
}

if (!org.hasOwnProperty('example')) {
    org.example = {};
}

org.example.AnotherObject = function () {
    // constructor body
};

Ben büyük taklit hayranı değilim, ama küresel kapsamı dışına taşımak istediğiniz birçok nesne varsa bu yararlı olabilir.


18

Kod organizasyonu, kuralların ve dokümantasyon standartlarının kabul edilmesini gerektirir:
1. Fiziksel bir dosya için ad alanı kodu;

Exc = {};


2. Bu ad alanlarındaki grup sınıfları javascript;
3. Gerçek dünyadaki nesneleri temsil etmek için Prototipler veya ilgili işlevler veya sınıflar ayarlayın;

Exc = {};
Exc.ui = {};
Exc.ui.maskedInput = function (mask) {
    this.mask = mask;
    ...
};
Exc.ui.domTips = function (dom, tips) {
    this.dom = gift;
    this.tips = tips;
    ...
};


4. Kodu geliştirmek için kurallar belirleyin. Örneğin, tüm dahili işlevlerini veya yöntemlerini bir nesne türünün class özelliğinde gruplayın.

Exc.ui.domTips = function (dom, tips) {
    this.dom = gift;
    this.tips = tips;
    this.internal = {
        widthEstimates: function (tips) {
            ...
        }
        formatTips: function () {
            ...
        }
    };
    ...
};


5. İsim alanları, sınıflar, metotlar ve değişkenlerin dokümantasyonunu yapar. Gerektiğinde bazı kodları da tartışın (bazı FI'lar ve Fors'lar, genellikle kodun önemli mantığını uygularlar).

/**
  * 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;
    ...
};


Bunlar sadece bazı ipuçları, ancak bu kodun düzenlenmesine büyük ölçüde yardımcı oldu. Başarılı olmak için disiplin sahibi olmanız gerektiğini unutmayın!


13

İyi OO tasarım ilkelerini ve tasarım modellerini takip etmek, kodunuzun bakımını ve anlaşılmasını kolaylaştırmak için uzun bir yol kat ediyor. Ancak son zamanlarda keşfettiğim en iyi şeylerden biri, yayınlama / abone olma gibi sinyaller ve yuvalardır. Basit bir jQuery uygulaması için http://markdotmeyer.blogspot.com/2008/09/jquery-publish-subscribe.html adresine bakın .

Bu fikir, GUI gelişimi için diğer dillerde de kullanılmaktadır. Kodunuzda bir yerde önemli bir şey olduğunda, diğer nesnelerdeki diğer yöntemlerin abone olabileceği global bir sentetik etkinlik yayınlarsınız. Bu, nesnelerin mükemmel şekilde ayrılmasını sağlar.

Bence Dojo (ve Prototip?) Bu tekniğin yerleşik bir versiyonuna sahip.

ayrıca bkz. Sinyaller ve yuvalar nedir?


Bunu jQuery'de yaptım. JS'nin yerleşik bir etkinlik modeli vardır, bu yüzden çok fazla çerçeve desteğine ihtiyacınız yoktur.
Marnen Laibow-Koser


11

Dojo ilk günden beri modül sistemine sahipti. Aslında, hepsini bir arada tutan tutkal Dojo'nun temel taşı olarak kabul edilir:

Dojo modüllerini kullanarak aşağıdaki hedeflere ulaşır:

  • Dojo kodu ve özel kod için ad alanları (dojo.declare() ) - global alanı kirletmez, diğer kütüphanelerle bir arada bulunur ve kullanıcının Dojo farkında olmayan kodu.
  • Modülleri ada göre eşzamanlı veya eşzamansız olarak yükleme (dojo.require() ).
  • Özel, yalnızca web uygulamanızın gereksinimlerini karşılamak için tek bir dosya veya bir grup bağımlı dosya (katmanlar olarak adlandırılır) oluşturmak üzere modül bağımlılıklarını analiz ederek oluşturulur. Özel yapımlar arasında Dojo modülleri ve müşteri tarafından sağlanan modüller de bulunabilir.
  • Dojo'ya ve kullanıcı koduna şeffaf CDN tabanlı erişim. Hem AOL hem de Google Dojo'yu bu şekilde taşıyor, ancak bazı müşteriler bunu özel web uygulamaları için de yapıyor.

9

JavasciptMVC'ye göz atın .

Yapabilirsin :

  • kodunuzu model, görünüm ve denetleyici katmanlarına ayırın.

  • tüm kodu tek bir üretim dosyasına sıkıştır

  • kodu otomatik oluştur

  • birim testleri oluşturma ve çalıştırma

  • ve daha fazlası ...

En iyisi, jQuery kullanır, böylece diğer jQuery eklentilerinden de yararlanabilirsiniz.


Evet, jmvc kullandım ve oldukça iyi - dokümanlar daha iyi olabilir
meouw

9

Patronum hala modüler kod (C dili) yazdıkları zamanlardan bahsediyor ve günümüzde kodun ne kadar berbat olduğundan şikayet ediyor! Programcıların herhangi bir çerçevede montaj yazabildikleri söylenir. Kod organizasyonunun üstesinden gelmek için her zaman bir strateji vardır. Temel sorun, java betiğini oyuncak olarak gören ve asla öğrenmeye çalışmayan adamlarla ilgilidir.

Benim durumumda, js dosyalarını uygun bir init_screen () ile UI teması veya uygulama ekranı temelinde yazıyorum. Uygun kimlik adlandırma kuralını kullanarak, kök öğe düzeyinde ad alanı çakışması olmadığından emin olun. Mütevazi window.load (), ben üst düzey kimliğe göre şeyler bağlamak.

Kesinlikle tüm özel yöntemleri gizlemek için java komut dosyası kapatma ve desenler kullanın. Bunu yaptıktan sonra, hiçbir zaman çelişen özellikler / işlev tanımları / değişken tanımlarıyla ilgili bir sorunla karşılaşmadınız. Bununla birlikte, bir ekiple çalışırken aynı titizliği uygulamak genellikle zordur.


9

MVC çerçevelerinden hiç kimsenin bahsetmediğine şaşırdım. Backbone.js kullanıyorumKodumu modülerleştirmek ve çözmek için ve çok değerli.

Dışarıda bu tür çerçevelerden birkaçı var ve çoğu da oldukça küçük. Benim kişisel görüşüm, gösterişli UI şeyler için sadece birkaç satır jQuery'den daha fazla yazacaksanız veya zengin bir Ajax uygulaması istiyorsanız, bir MVC çerçevesinin hayatınızı çok daha kolay hale getireceği yönündedir.


8

"Deli gibi yaz ve sadece en iyisi için çalışıyor umuyoruz?", Ben sadece 2 geliştirici tarafından geliştirilen ve sürdürülen böyle bir proje gördüm, çok sayıda javascript kodu ile büyük bir uygulama. Üstelik aklınıza gelebilecek her olası jquery işlevi için farklı kısayollar vardı. Sınıf, modül, ad alanı ... ve tüm evrenin jquery eşdeğeri olduğu için kodu eklenti olarak düzenlemelerini önerdim. Ancak işler çok daha kötüye gitti, şimdi projede kullanılan 3 kod satırının her bir kombinasyonunun yerini alan eklentiler yazmaya başladılar. Kişisel olarak jQuery şeytan olduğunu düşünüyorum ve çok fazla javascript ile projelerde kullanılmamalıdır çünkü tembel olmak ve herhangi bir şekilde kod organize düşünmek için teşvik eder. 40 zincirli jQuery fonksiyonları ile bir satır daha 100 satır javascript okumak istiyorum (I ' m şaka yapmıyorum). Popüler inanışın aksine, javascript kodunu ad alanlarına ve sınıflara eşdeğer olarak düzenlemek çok kolaydır. YUI ve Dojo bunu yapar. İsterseniz kendiniz kolayca yuvarlayabilirsiniz. YUI'nin yaklaşımını çok daha iyi ve verimli buluyorum. Ancak, yararlı bir şey yazmak istiyorsanız, YUI adlandırma kurallarını telafi etmek için snippet'leri destekleyen güzel bir editöre ihtiyacınız vardır.


3
Size gerçekten uzun, zincirleme komutlar konusunda katılıyorum, ancak jQuery'nin en iyi kısımlarından biri, tüm Javascript'i HTML'den uzak tutmasıdır. Kimlik eklemeye "gerek duymadan" veya öğelerinizdeki <whatever> olaylarında tüm öğeleriniz için olay işleyicileri ayarlayabilirsiniz. Her zaman olduğu gibi, herhangi bir aracın aşırı kullanımı kötü ...
Hugoware

JQuery'de büyük, iyi organize edilmiş projeler üzerinde çalıştım. Bunun organizasyona neden girdiğini düşündüğünüzü bilmiyorum.
Marnen Laibow-Koser

7

Ekranda birkaç kez başlatmaya gerek duymadığım her şey için tek tonlar, her şey için bir sınıf oluşturuyorum. Ve hepsi aynı dosyada aynı isim alanına konur. Her şey yorumlanır ve UML, durum diyagramları ile tasarlanır. Javascript kodu html açık olduğundan satır içi javascript ve ben çapraz tarayıcı sorunları en aza indirmek için jquery kullanma eğilimindedir.


3
iyi yorum ANAHTAR - bunu söyledi sevindim bu yüzden zorunda değildi. Tutarlı adlandırma kuralları, değişkenler için kolayca anlaşılabilir bir organizasyon stratejisi ve amp; fonksiyonlar ve daha önce de belirtildiği gibi, sınıfların tekillere karşı mantıklı kullanımı.
matt lohkamp

Hayır. Yorumlara ihtiyacınız varsa, kodunuz genellikle yeterince okunamaz. Yorum gerektirmeyen kod yazmaya çalışın.
Marnen Laibow-Koser

Ayrıca, UML ve durum diyagramlarına ihtiyacınız varsa, bu muhtemelen mimarinizin koddan yeterince açık olmadığı anlamına gelir. Downvoting.
Marnen Laibow-Koser

1
@Marnen İyi yazılmış projeler, mutlaka NEDEN değil, NEDEN'i açıklayan yorumları içerir. Kod zaten NE'yi tanımlar, ancak çoğu zaman NEDEN'i tanımlamak için bir şeye ihtiyacınız vardır. Upvoting.
Cypher

@Cypher İyi yazılmış projeler, sadece "neyi" değil, genellikle "neden" i söyleyebileceğiniz yeterince açık bir koda sahiptir. Ben "neden" söylemek için bir yorum güvenemem, çünkü kod ile senkronize olduğunu garanti yok. Kod belgesinin kendisini bırakın.
Marnen Laibow-Koser

6

Son projem -Viajeros.com- Birkaç tekniğin bir kombinasyonunu kullandım. Nasıl bir web uygulaması düzenlemek için bilmiyorum - Viajeros iyi tanımlanmış bölümleri olan gezginler için bir sosyal ağ sitesi, bu yüzden her alan için kodu ayırmak kolaydır.

Site bölümüne göre ad alanı simülasyonu ve modüllerin tembel yüklemesini kullanıyorum. Her sayfa yükünde bir "vjr" nesnesi bildiririm ve her zaman ona bir dizi ortak işlev yüklerim (vjr.base.js). Daha sonra her HTML sayfası hangi modüllerin basit bir şekilde ihtiyaç duyduğuna karar verir:

vjr.Required = ["vjr.gallery", "vjr.comments", "vjr.favorites"];

Vjr.base.js her birini sunucudan sıkıştırır ve yürütür.

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"
      });
    }
  }
};

Her "modül" şu yapıya sahiptir:

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);

Sınırlı Javascript bilgim göz önüne alındığında, bunu yönetmenin daha iyi yollarının olması gerektiğini biliyorum, ama şimdiye kadar bizim için harika çalışıyor.


6

Kodunuzu bir Jquery merkezli NameSpace şekilde düzenlemek aşağıdaki gibi görünebilir ... ve Prototype, Ext gibi diğer Javascript API'leri ile çakışmayacaktır.

<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>

Bu yardımcı olur umarım.


Bu bana küçük bir kargo mühendisi olarak dikkat çekiyor. jQuery yapıcı işlevinin yeni bir örneğini döndürdüğü jQuery.fniçin jQuery.prototype, bir işaretçidir $(). JQuery'ye bir 'eklenti' eklemek, sadece prototipini genişletmek anlamına gelir. Ama yaptığınız şey bu değil ve aynı şeyi başarmanın daha temiz yolları var.
Adam Lassek

Sadece statik işlevler yarattığına inanıyorum. JQuery'nin belgelerinde, statik işlevleri bildirmenin bu yolunun kabul edilebilir olduğunu hatırlıyorum
Alex Heyd

6

İyi OO + MVC müdürü, karmaşık bir javascript uygulamasını yönetmek için kesinlikle uzun bir yol kat edecektir.

Temel olarak uygulamamı ve javascriptimi aşağıdaki tanıdık tasarıma göre düzenliyorum (masaüstü programlama günlerimden Web 2.0'a kadar olan)

JS OO ve MVC

Görüntüdeki sayısal değerlerin açıklaması:

  1. Uygulamamın görüşlerini temsil eden widget'lar. Bu, genişletilebilir olmalı ve MVC'nin widget'ımı bir spagetti koduna (web uygulamasında büyük bir Javascript bloğunu doğrudan HTML'ye koymaya eşdeğer) dönüştürmek yerine elde etmeye çalıştığı düzgün bir şekilde sonuçlanan iyi bir ayırma olmalıdır. Her pencere öğesi, diğer pencere öğeleri tarafından oluşturulan etkinliği dinleyerek başkaları aracılığıyla iletişim kurarak, yönetilemez koda yol açabilecek pencere öğeleri arasındaki güçlü bağlantıyı azaltır (komut dosyası etiketindeki genel işlevlere işaret eden her yere onclick eklediğiniz günü hatırlayın?
  2. Pencere öğelerinde doldurmak ve sunucuya iletmek istediğim verileri temsil eden nesne modelleri. Verileri modeline ekleyerek, uygulama veri formatı agnostik haline gelir. Örneğin: Javascript'te doğal olarak bu nesne modelleri çoğunlukla serileştirilir ve JSON'a serileştirilirken, sunucu bir şekilde iletişim için XML kullanıyorsa, tek yapmam gereken serileştirme / serileştirme katmanını değiştirmek ve tüm widget sınıflarını değiştirmek zorunda değildir. .
  3. İş mantığını ve sunucuya iletişimi + zaman zaman önbellekleme katmanını yöneten denetleyici sınıfları. Bu katman sunucuya iletişim protokolünü kontrol eder ve nesne modellerine gerekli verileri koyar
  4. Sınıflar, karşılık gelen ad alanlarına düzgün bir şekilde sarılır. Eminim hepimiz Javascript'te ne kadar kötü global isim alanının olabileceğini biliyoruz.

Geçmişte, dosyaları kendi js'lerine ayırır ve Javascript'te OO ilkeleri oluşturmak için ortak uygulamayı kullanırdım. Yakında JS OO yazmanın birçok yolu olduğunu bulduğum problem ve tüm ekip üyelerinin aynı yaklaşıma sahip olması gerekmez. Takım büyüdükçe (benim durumumda 15 kişiden fazla), Nesne Odaklı Javascript için standart bir yaklaşım olmadığı için bu durum karmaşıklaşıyor. Aynı zamanda kendi çerçevemi yazmak ve çözdüğümden daha akıllı insanlardan emin olduğum bazı çalışmaları tekrarlamak istemiyorum.

jQuery, Javascript Framework kadar inanılmaz derecede güzel ve seviyorum, ancak proje büyüdükçe, özellikle OO uygulamasını standartlaştırmak için web uygulamam için açıkça ek yapıya ihtiyacım var. Kendim için, birkaç deneyden sonra, YUI3 Tabanı ve Widget ( http://yuilibrary.com/yui/docs/widget/ ve http://yuilibrary.com/yui/docs/base/index.html ) altyapısının sağladığını görüyorum tam ihtiyacım olan şey. Onları kullanmamın birkaç nedeni.

  1. Ad Alanı desteği sağlar. OO ve kodunuzun düzgün bir şekilde organize edilmesi için gerçek bir ihtiyaç
  2. Sınıf ve nesne kavramını destekler
  3. Sınıfınıza örnek değişkenleri eklemek için standart bir yöntem sunar
  4. Sınıf uzantısını düzgün bir şekilde destekler
  5. Yapıcı ve yıkıcı sağlar
  6. Oluşturma ve olay bağlama sağlar
  7. Temel widget çerçevesine sahiptir
  8. Her widget artık standart olay tabanlı modeli kullanarak birbirleriyle iletişim kurabiliyor
  9. En önemlisi, tüm mühendislere Javascript geliştirme için bir OO Standardı verir.

Birçok görüşün aksine, jQuery ve YUI3 arasında seçim yapmak zorunda değilim. Bu ikisi barış içinde bir arada var olabilir. YUI3 karmaşık web uygulamam için gerekli OO şablonunu sunarken, jQuery hala ekibime hepimizin sevdiği ve aşina olduğu JS Abstraction'ı kullanmasını sağlıyor.

YUI3 kullanarak, Model olarak Bankası genişleten sınıfları, bir Görünüm olarak Widget genişleten sınıfları ayırarak ve gerekli mantık ve sunucu tarafı çağrıları yapan Controller sınıfları var MVC desen oluşturmayı başardılar.

Widget, olay tabanlı modeli kullanarak ve olayı dinleyerek ve önceden tanımlanmış arabirime dayalı gerekli görevi gerçekleştirerek birbirleriyle iletişim kurabilir. Basitçe söylemek gerekirse, OO + MVC yapısını JS'ye koymak benim için bir zevk.

Sadece bir feragatname, Yahoo! ve sadece asıl sorunun ortaya koyduğu sorunla baş etmeye çalışan bir mimar. Bence biri eşdeğer OO çerçevesi bulursa, bu da işe yarayacaktır. Prensip olarak, bu soru diğer teknolojiler için de geçerlidir. Programlama günlerimizi daha yönetilebilir hale getirmek için OO Prensipleri + MVC ile gelen tüm insanlar için şükürler olsun.


5

Kullandığım Dojo en paket yönetimi ( dojo.requireve dojo.provide) ve (sınıf sistemini dojo.declareayrı dosyalar halinde benim sınıfları / widget tüm modülarize da basit çoklu miras sağlar). Bu sadece kodunuzu organize tutmakla kalmaz, aynı zamanda sınıfların / widget'ların tembel / tam zamanında yüklenmesini sağlar.


3

Birkaç gün önce 37Signals'daki çocuklar bir RTE kontrolü yayınladılar . Javascript dosyalarını bir tür ön işlemci komutu kullanarak bir araya getiren bir kütüphane yaptılar.

JS dosyalarımı ayırmak için kullanıyorum ve sonunda onları bir olarak birleştiriyorum. Bu şekilde endişeleri ayırabilirim ve sonunda borudan geçen sadece bir dosyaya sahip olabilirim (gzip, daha az değil).

Şablonlarınızda, geliştirme modunda olup olmadığınızı kontrol edin ve ayrı dosyaları ekleyin ve üretimde sonuncuyu ekleyin (kendiniz "derlemeniz" gerekir).


1
getsprockets.org doğrudan bağlantıdır
Matt Gardner

3

Sahte sınıflar oluşturun ve mantıklı olan ayrı bir işleve atılabilecek her şeyin böyle yapıldığından emin olun. Ayrıca çok yorum yaptığınızdan ve spagghetti kodu yazmamaya dikkat edin, hepsini bölümlerde saklayın. Örneğin, ideallerimi gösteren bazı saçma kodlar. Açıkçası, gerçek hayatta, işlevlerini temel alan birçok kütüphane de yazıyorum.

$(function(){
    //Preload header images
    $('a.rollover').preload();

    //Create new datagrid
    var dGrid = datagrid.init({width: 5, url: 'datalist.txt', style: 'aero'});
});

var datagrid = {
    init: function(w, url, style){
        //Rendering code goes here for style / width
        //code etc

        //Fetch data in
        $.get(url, {}, function(data){
            data = data.split('\n');
            for(var i=0; i < data.length; i++){
                //fetching data
            }
        })
    },
    refresh: function(deep){
        //more functions etc.
    }
};


2

Bunun DDD (Domain-Driven Design) ile bağlantılı olduğunu düşünüyorum. Resmi bir API eksik olmasına rağmen üzerinde çalıştığım uygulama, sunucu tarafı kodu (sınıf / dosya adları, vb) yoluyla böyle ipuçları verir. Bununla silahlı, tüm sorun etki alanı için bir kapsayıcı olarak üst düzey bir nesne oluşturdum; daha sonra, gerektiğinde ad alanları ekledim:

var App;
(function()
{
    App = new Domain( 'test' );

    function Domain( id )
    {
        this.id = id;
        this.echo = function echo( s )
        {
            alert( s );
        }
        return this;
    }
})();

// separate file
(function(Domain)
{
    Domain.Console = new Console();

    function Console()
    {
        this.Log = function Log( s )
        {
            console.log( s );
        }
        return this;
    }
})(App);

// implementation
App.Console.Log('foo');

2

JavaScript kuruluşu aşağıdakileri kullanıyorsa

  1. Tüm javascriptiniz için klasör
  2. Sayfa düzeyinde javascript, kendi sayfasını aynı sayfayla aynı adla alır. ProductDetail.aspx, ProductDetail.js olur
  3. Kütüphane dosyaları için javascript klasörünün içinde bir lib klasörü var
  4. İlgili kitaplık işlevlerini, uygulamanız boyunca kullanmak istediğiniz bir lib klasörüne yerleştirin.
  5. Ajax, javascript klasörünün dışına taşıdığım ve kendi klasörünü alan tek javascripttir. Sonra istemci ve sunucu olmak üzere iki alt klasör ekliyorum
  6. İstemci klasörü tüm .js dosyalarını alırken, sunucu klasörü tüm sunucu tarafı dosyalarını alır.

Dosya organizasyonu için güzel. Bunu kodla yapıyorum. Ama sonunda kodumu derleme ... dll diyelim. Javascript ile de buna ihtiyacınız var, ya da sayfa başına 15 js dosyası talep edeceksiniz.
graffic

Sayfa başına 15 JS dosyası istemede yanlış bir şey yok. Tarayıcınız, sonraki istekler için bunları önbelleğe alır.
Marnen Laibow-Koser

@ MarnenLaibow-Koser Bir sayfada 15 JS dosyası istemekle ilgili tek sorun, tarayıcının bir seferde kaç HTTP isteğinin işlenebileceğidir. Bu nedenle, bunları tek bir dosyada paketlemek, tarayıcının aynı anda diğer gerekli dosyaları istemesini sağlar.
iwasrobbed

Bu doğru, ancak ilk birkaç isabetten sonra tarayıcının önbelleğinde olacaklar, bu yüzden HTTP bağlantıları gerektirmeyecekler.
Marnen Laibow-Koser

2

Bu küçük şeyi kullanıyorum. Hem JS hem de HTML şablonları için 'dahil et' talimatı verir. Bu karışıklığı tamamen ortadan kaldırıyor.

https://github.com/gaperton/include.js/

$.include({
    html: "my_template.html" // include template from file...
})
.define( function( _ ){ // define module...
    _.exports = function widget( $this, a_data, a_events ){ // exporting function...
        _.html.renderTo( $this, a_data ); // which expands template inside of $this.

        $this.find( "#ok").click( a_events.on_click ); // throw event up to the caller...
        $this.find( "#refresh").click( function(){
            widget( $this, a_data, a_events ); // ...and update ourself. Yep, in that easy way.
        });
    }
});

2

Sen kullanabilirsiniz jQuery mx Eğer modelleri, görünümleri ve denetleyicileri kullanmasına izin verir komut kümesidir (javascriptMVC kullanılır). Bir projede kullandım ve sıkıştırma nedeniyle minimum komut dosyası boyutlarıyla yapılandırılmış javascript oluşturmama yardımcı oldum. Bu bir kontrolör örneğidir:

$.Controller.extend('Todos',{
  ".todo mouseover" : function( el, ev ) {
   el.css("backgroundColor","red")
  },
  ".todo mouseout" : function( el, ev ) {
   el.css("backgroundColor","")
  },
  ".create click" : function() {
   this.find("ol").append("<li class='todo'>New Todo</li>"); 
  }
})

new Todos($('#todos'));

Görünüm ve model parçalarıyla ilgilenmiyorsanız jquerymx'in yalnızca denetleyici tarafını da kullanabilirsiniz .


1

Sorunuz geçen yıl beni rahatsız eden bir soru. Fark - kodu, özel ve genel yöntemleri hiç duymamış yeni geliştiricilere dağıtmak. Basit bir şey inşa etmek zorunda kaldım.

Sonuç, nesne değişmezlerini jQuery'ye çeviren küçük (yaklaşık 1 KB) bir çerçeveydi. Sözdiziminin taranması görsel olarak daha kolaydır ve js'niz gerçekten büyürse, kullanılan seçiciler, yüklenen dosyalar, bağımlı işlevler vb. Gibi şeyleri bulmak için yeniden kullanılabilir sorgular yazabilirsiniz.

Burada küçük bir çerçeve yayınlamak pratik değildir, bu yüzden örneklerle bir blog yazısı yazdım (İlkim. Bu bir maceraydı!). Bir göz atabilirsiniz.

Burada kontrol etmek için birkaç dakika ile diğerleri için, ben çok teşekkür ederiz!

FireFox, nesne sorgusu örneği için toSource () öğesini desteklediğinden önerilir.

Şerefe!

Adem


0

Ben olay işleyicilerinin çoğunu depolamak için Ben Nolan'ın davranışından esinlenen özel bir komut dosyası kullanıyorum (bunun için şu anki bağlantıyı ne yazık ki bulamıyorum). Bu olay işleyicileri, örneğin className veya Id öğeleri tarafından tetiklenir. Misal:

Behaviour.register({ 
    'a.delete-post': function(element) {
        element.observe('click', function(event) { ... });
    },

    'a.anotherlink': function(element) {
        element.observe('click', function(event) { ... });
    }

});

Global davranış içerenler dışında Javascript kütüphanelerimin çoğunu anında eklemeyi seviyorum. Bunun için Zend Framework'ün headScript () yer tutucu yardımcısını kullanıyorum , ancak Ajile ile anında diğer komut dosyalarını yüklemek için javascript'i de kullanabilirsiniz .


Aradığın şey bu mu? koders.com/javascript/…
DOK

Evet, bu! :) Bağlantının arkasındaki kod, ilham aldığım sürümden oldukça yeni gibi görünüyor. Emeğin için teşekkürler!
Aron Rotteveel

0

Sunucu tarafı dilinizin ne olduğunu söylemezsiniz. Veya daha kalıcı olarak, sunucu tarafında hangi çerçeveyi - varsa) kullanıyorsunuz.

IME, sunucu tarafında bir şeyler düzenliyorum ve her şeyin web sayfasında sallanmasına izin veriyorum. Çerçeveye, yalnızca her sayfanın yüklemesi gereken JS'yi değil, aynı zamanda oluşturulan işaretleme ile çalışan JS parçalarını düzenleme görevi verilir. Genellikle bir kereden fazla yayılmasını istemediğiniz bu tür parçalar - bu yüzden bu kodun bu soruna bakması için çerçeveye dahil edilirler. :-)

Kendi JS'lerini yayınlaması gereken son sayfalar için, genellikle oluşturulan biçimlendirmede mantıklı bir yapı olduğunu fark ederim. Bu tür lokalize JS genellikle böyle bir yapının başlangıcında ve / veya sonunda birleştirilebilir.

Bunların hiçbirinin etkili JavaScript yazmanızı engellemediğini unutmayın! :-)


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.