Загальноприйняті найкращі практики щодо організації коду в JavaScript [закрито]


561

Оскільки рамки JavaScript, такі як jQuery, роблять веб-додатки на базі клієнтів багатшими та функціональнішими, я почав помічати одну проблему ...

Як у світі ви тримаєте це організовано?

  • Покладіть всі ваші обробники на одне місце і запишіть функції на всі події?
  • Створити функції / класи, щоб охопити всю свою функціональність?
  • Пишіть як божевільний і просто сподіваєтесь, що це виходить найкращим?
  • Відмовитися і отримати нову кар’єру?

Я згадую jQuery, але це взагалі будь-який код JavaScript. Я знаходжу, що коли рядки на рядках починають накопичуватися, стає важче керувати файлами скриптів або знаходити те, що ви шукаєте. Цілком можливо, найбільші проблеми, які я знайшов, є так багато способів зробити те саме, що важко дізнатися, який з них є поточним загальноприйнятим найкращим досвідом.

Чи є якісь загальні рекомендації щодо найкращого способу збереження .js- файлів настільки ж приємними та акуратними, як і решта вашої програми? Або це лише питання IDE? Чи є кращий варіант там?


EDIT

Це питання передбачало більше про організацію коду, а не про організацію файлів. Було кілька справді хороших прикладів об’єднання файлів або розділення вмісту навколо.

Моє запитання: який є загальноприйнятий найкращий спосіб організації власного коду? Який ваш спосіб чи навіть рекомендований спосіб взаємодії з елементами сторінки та створення коду для повторного використання, який не суперечить один одному?

Деякі люди перераховували простори імен, що є хорошою ідеєю. Які ще є способи, більш конкретно поводження з елементами на сторінці та збереження впорядкованого та чіткого коду?


хтось, хто насправді знайшов час, щоб поговорити про організацію коду, а не "просто", який інструмент він використовує для об'єднання та стиснення своїх файлів JS: stackoverflow.com/questions/16736483/…
Adrien Be

Відповіді:


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

Я розміщую різні "простори імен", а іноді й окремі класи в окремі файли. Зазвичай я починаю з одного файлу, і оскільки клас чи простір імен отримують достатньо великих розмірів, щоб гарантувати його, я відокремлюю його у свій власний файл. Використання інструменту для комбінування всіх файлів для виробництва - також відмінна ідея.


24
Я зазвичай називаю це "крокфордським шляхом". +1 від мене
Метт Бріггс

4
Можна навіть піти трохи далі. Перейдіть за цим посиланням: wait-till-i.com/2007/08/22/…
MKroehnert

4
@MattBriggs інакше називається the, module patternі він заснований на IIFE pattern.
Адріан Бе

Вам не потрібно якось експортувати класи? Як створюється об'єкт із зовнішнього боку такого модуля? Чи повинен бути метод createNewSomething()у поверненому об'єкті, тому створення об'єкта відбувається виключно в межах модуля? Гм ... я б очікував, що класи (конструктори) помітні ззовні.
robsch

@robsch Його приклад не приймає жодних параметрів, але більшість би. Дивіться мій приклад тут , як це зазвичай робиться (машинопис, але 99% такі ж): repl.it/@fatso83/Module-Pattern-in-TypeScript
oligofren

88

Я намагаюся уникати будь-якого JavaScript з HTML. Весь код інкапсульований у класи, і кожен клас має свій власний файл. Для розробки я маю окремі теги <script> для включення кожного файлу js, але вони об'єднуються в один більший пакет для виробництва, щоб зменшити накладні витрати HTTP-запитів.

Як правило, у мене буде один "головний" js-файл для кожної програми. Отже, якби я писав додаток "опитування", я мав би файл js під назвою "survey.js". Це буде містити точку входу в код jQuery. Я створюю посилання jQuery під час отримання екземплярів і потім передаю їх у свої об'єкти як параметри. Це означає, що класи javascript є "чистими" і не містять посилань на ідентифікатори CSS або імена класів.

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

Я також вважаю, що конвенція про іменування є важливою для читабельності. Наприклад: Я додаю 'j' до всіх екземплярів jQuery.

У наведеному вище прикладі є клас під назвою 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>');
  //...
};

Я створив кілька досить складних програм, використовуючи цей підхід.


15
Я вважаю, що використання $префікса імені змінної є більш поширеною практикою, але я можу помилитися. Тож $s = $('...')замість цього jS = $('...'), я думаю, лише питання переваги. Цікаво, однак, оскільки угорські позначення вважаються кодовим запахом. Дивно, наскільки деякі мої конвенції / налаштування коду JavaScript відрізняються від моїх умов C # / Java щодо кодування.
jamiebarrow

9
@jamie У цьому випадку це не кодовий запах, це саме один з небагатьох випадків, коли угорська є доброю . Ви можете прочитати це .
Дан Абрамов

3
@DanAbramov дякую за посилання. Я справді повинен прочитати всі блоги Джоеля, він так добре пояснює речі. Однозначно заслуговує на славу / репутацію, яку він має. Я буду називати Systems Hungarianзапах коду і Apps Hungarianяк практику відтепер :)
jamiebarrow

Я думаю, що у світі C # це також може бути чудовою статтею для сприяння використанню var, тепер, коли я думаю про це. Більшість аргументів проти використання var- це те, коли ви не будете впевнені в тому, що ви 'повертаєте', але я думаю, що аргумент повинен бути проти того, щоб не знати «класу» того, що повертається. Якщо ви користуєтеся Угорською програмою, ви не повинні турбуватись про це ... цікаво.
jamiebarrow

3
@Marnen: Я бачу вашу думку, але це не марно як керівництво програмісту. Префікс $ нагадує мені, що це таке під час читання мого коду пізніше, і таким чином допомагає швидше зрозуміти.
Шон

39

Ви можете розбити свої сценарії на окремі файли для розробки, а потім створити "релізну" версію, де ви стискаєте їх разом і запускаєте YUI Compressor або щось подібне на ньому.


Іноді є непотрібні сценарії javascript. Марно відправляти їх клієнту. Я думаю, що це лише відправити те, що потрібно. Звичайно, для веб-додатків, які використовуються цілий день, наприклад, інтранет-додаток, може бути краще, щоб надіслати всю партію одразу під час завантаження першої сторінки.
DOK

2
Компіляція @DOK повинна включати висічення невикористаних речей.
aehlke

Існує також концепція ледачого завантаження, щоб спробувати зменшити пропускну здатність, де ви завантажуєте початкову сторінку, а потім виконуєте асинхронне завантаження необхідних файлів сценаріїв (як зазначено в інших відповідях на це питання). Хоча це може зажадати більше запитів і насправді може бути менш корисним. @DOK, якщо JS є кешованим, один середній запит може бути кращим, ніж кілька невеликих.
jamiebarrow

27

Натхненний попередніми повідомленнями, я зробив копію каталогів Rakefile та постачальників, розповсюджених за допомогою WysiHat (RTE, згаданий змінним журналом), і зробив декілька модифікацій, щоб включити перевірку коду за допомогою JSLint та мінімізацію з YUI Compressor .

Ідея полягає в тому , щоб використовувати Зірочки (від WysiHat) , щоб об'єднати кілька JavaScripts в один файл, перевірте синтаксис об'єднаного файлу з JSLint і применшувати його з YUI Compressor перед розподілом.

Передумови

  • Час виконання Java
  • коштовний камінь з рубіном і граблями
  • Ви повинні знати, як ввести JAR в Classpath

Тепер зробіть

  1. Завантажте Rhino і поставте JAR ("js.jar") на свій класний шлях
  2. Завантажте компресор YUI і поставте JAR (build / yuicompressor-xyz.jar) на свій класний шлях
  3. Завантажте WysiHat і скопіюйте каталог "постачальник" у корінь вашого JavaScript-проекту
  4. Завантажте JSLint для Rhino та покладіть його у каталог "постачальника"

Тепер створіть файл з назвою "Rakefile" у кореневій каталозі проекту JavaScript та додайте до нього такий вміст:

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

Якщо ви все зробили правильно, ви повинні мати можливість використовувати наступні команди у своїй консолі:

  • rake merge - об'єднати різні файли JavaScript в один
  • rake check- перевірити синтаксис свого коду (це завдання за замовчуванням , тому ви можете просто ввести rake)
  • rake minify - підготувати мінімізовану версію свого JS-коду

На злиття джерела

Використовуючи зірочки, попередній процесор 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
})();

І потім...

Погляньте на Rakefile, який постачається з WysiHat, щоб налаштувати тестування автоматизованого блоку. Приємні речі :)

А тепер для відповіді

Це не дуже добре відповідає на початкове запитання. Я знаю і мені про це шкода, але я розмістив це тут, тому що сподіваюся, що хтось інший може бути корисним для організації їхнього безладу.

Мій підхід до проблеми полягає в тому, щоб зробити якомога більше об'єктно-орієнтованого моделювання та розділити реалізацію на різні файли. Тоді обробники повинні бути якомога коротшими. Приклад із Listсинглтоном також приємний.

І простори імен ... ну вони можуть бути імітовані глибшою структурою об'єкта.

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

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

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

Я не великий прихильник наслідувань, але це може бути корисно, якщо у вас є багато об'єктів, які ви хотіли б вийти з глобальної сфери.


18

Організація коду вимагає прийняття конвенцій та стандартів документації:
1. Код простору імен для фізичного файлу;

Exc = {};


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


4. Встановити умови для поліпшення коду. Наприклад, згрупуйте всі його внутрішні функції або методи в атрибуті класу типу об'єкта.

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


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


Це лише кілька порад, але це дуже допомогло в організації коду. Пам’ятайте, що для успіху ви повинні мати дисципліну!


13

Слідуючи хорошим принципам дизайну OO та моделям дизайну проходить довгий шлях до полегшення коду для обслуговування та розуміння. Але одне з найкращих речей, які я нещодавно виявив, - це сигнали та слоти, які публікуються та підписуються. Подивіться на http://markdotmeyer.blogspot.com/2008/09/jquery-publish-subscribe.html для простої реалізації jQuery.

Ідея добре використовується іншими мовами для розробки графічного інтерфейсу. Коли десь у вашому коді відбувається щось істотне, ви публікуєте глобальну синтетичну подію, на яку можуть підписатися інші методи в інших об'єктах. Це дає відмінне розділення предметів.

Я думаю, що у Dojo (і прототипу?) Є вбудована версія цієї методики.

див. також Що таке сигнали та слоти?


Я це робив у jQuery. JS має вбудовану модель подій, тому вам не дуже потрібна підтримка рамки.
Marnen Laibow-Koser

12

Мені вдалося успішно застосувати шаблон модуля Javascript до програми Ext JS на попередній роботі. Він надав простий спосіб створити красиво інкапсульований код.


11

У Доджо була система модулів з першого дня. Насправді він вважається наріжним каменем Dojo, клеєм, який тримає його разом:

Використовуючи модулі Dojo досягає наступних цілей:

  • Простори імен для коду Dojo та спеціального коду ( dojo.declare()) - не забруднюють глобальний простір, співіснують з іншими бібліотеками та невідомими кодом користувача.
  • Завантаження модулів синхронно або асинхронно за назвою ( dojo.require()).
  • Спеціальна побудова шляхом аналізу залежностей модулів для створення одного файлу або групи взаємозалежних файлів (так званих шарів), щоб включати лише те, що потрібно вашому веб-додатку. Спеціальні збірки можуть також включати модулі Dojo та модулі, що постачаються клієнтом.
  • Прозорий доступ на основі CDN до Dojo та коду користувача. І AOL, і Google здійснюють Dojo таким чином, але деякі клієнти роблять це і для своїх спеціальних веб-додатків.

9

Перевірте JavasciptMVC .

Ти можеш :

  • розділіть свій код на шари моделі, перегляду та контролера.

  • стиснути весь код в один виробничий файл

  • автоматично генерувати код

  • створювати та запускати одиничні тести

  • та багато іншого ...

Найкраще, що він використовує jQuery, тому ви можете скористатися іншими jQuery плагінами.


Так, я використовував jmvc і це дуже добре - документи можуть бути краще , хоча
meouw

9

Мій начальник все ще говорить про часи, коли вони писали модульний код (мова С), і скаржиться на те, наскільки шалений код зараз! Кажуть, що програмісти можуть писати збірку в будь-яких рамках. Завжди існує стратегія подолання організації коду. Основна проблема полягає у хлопцях, які розглядають сценарій Java як іграшку і ніколи не намагаються її навчитись.

У моєму випадку я записую js-файли на основі теми інтерфейсу або екрану програми, з належним init_screen (). Використовуючи правильну конвенцію іменування ідентифікаторів, я переконуюсь у відсутності конфліктів простору імен на рівні кореневих елементів. У ненав'язливому window.load () я прив'язую речі на основі ідентифікатора верхнього рівня.

Я строго використовую закриття та шаблони сценаріїв Java, щоб приховати всі приватні методи. Після цього жодного разу не стикався з проблемою конфліктуючих властивостей / визначень функцій / визначень змінних. Однак, працюючи з командою, часто важко застосувати однакову жорсткість.


9

Я здивований, що ніхто не згадував рамки MVC. Я використовую Backbone.js для модуляції та декупажу коду, і це було безцінним.

Існує досить багато таких типів каркасів там, і більшість з них теж крихітні. Моя особиста думка полягає в тому, що якщо ви збираєтеся написати більше, ніж просто пару рядків jQuery для кричущих інтерфейсів інтерфейсу, або хочете багата програма Ajax, рамки MVC полегшать ваше життя.


8

"Пишіть як божевільний і просто сподіваюся, що це вийде найкраще?", Я бачив такий проект, який розробили та підтримували лише 2 розробники, величезне додаток з великою кількістю коду javascript. Крім того, були різні ярлики для кожної можливої ​​функції jquery, яку ви можете придумати. Я запропонував їм організувати код як плагіни, оскільки це еквівалент jquery класу, модуля, простору імен ... і всього Всесвіту. Але все погіршилося, тепер вони почали писати плагіни, замінюючи кожну комбінацію з 3 рядків коду, використаних у проекті. Особисто я думаю, що jQuery - це диявол, і його не слід використовувати в проектах з великою кількістю JavaScript, тому що це спонукає вас лінуватися і не думати про організацію коду в жодному разі. Я вважаю за краще прочитати 100 рядків javascript, ніж один рядок з 40 ланцюговими функціями jQuery (я ' м не жартую). Всупереч поширеній думці, дуже легко організувати код JavaScript в еквіваленті простору імен та класів. Так роблять YUI і Dojo. Якщо ви хочете, ви можете легко закатати свою. Я вважаю підхід YUI набагато кращим та ефективнішим. Але вам зазвичай потрібен гарний редактор з підтримкою фрагментів, щоб компенсувати умови іменування YUI, якщо ви хочете написати щось корисне.


3
Я погоджуюся з вами щодо дійсно довгих ланцюгових команд, але одна з найкращих частин jQuery полягає в тому, що він не підтримує всі JavaScript від HTML. Ви можете налаштувати обробники подій для всіх своїх елементів, не «додаючи» ідентифікатори або <<що б> не було подій на своїх елементах. Як завжди, над використанням будь-якого інструменту погано ...
Hugoware

Я працював над величезними, добре організованими проектами в jQuery. Я не знаю, чому ви вважаєте, що це перешкоджає організації.
Marnen Laibow-Koser

7

Я створюю одинаки для кожної речі, яку мені справді не потрібно інстанціювати кілька разів на екрані, заняття для всього іншого. І всі вони розміщуються в одному просторі імен в одному файлі. Все коментується та проектується за допомогою UML-діаграм стану. Код javascript не має HTML, тому немає вбудованого JavaScript, і я схильний використовувати jquery для мінімізації проблем із перехресним браузером.


3
хороший коментар КЛЮЧОВИЙ - Я радий, що ви сказали це, тому мені не довелося. Я б додав послідовних угод про іменування, якусь легко зрозумілу організаційну стратегію змінних & amp; функції, і як ви вже згадували, розумне використання класів проти одинакових.
matt lohkamp

Ні. Якщо вам потрібні коментарі, ваш код, як правило, недостатньо читабельний. Прагніть писати код, який не потребує коментарів.
Marnen Laibow-Koser

Крім того, якщо вам потрібні діаграми UML та стану, це, ймовірно, означає, що ваша архітектура недостатньо чітка з коду. Схильність
Marnen Laibow-Koser

1
@Marnen Добре написані проекти містять коментарі, щоб описати ЧОМУ, не обов'язково ЩО. У коді вже описано, ЩО, але часто вам потрібно щось описати, ЧОМУ. Оголошення.
Cypher

@Cypher Добре написані проекти мають достатньо чіткий код, який зазвичай можна сказати "чому", а не лише "що". Я б не довірив коментарю сказати мені "чому", тому що я не гарантую, що він синхронізований з кодом. Нехай сам код документа.
Marnen Laibow-Koser

6

У своєму останньому проекті -Viajeros.com- я використав комбінацію декількох прийомів. Я б не знав, як організувати веб-додаток - Viajeros - це веб-сайт у соціальних мережах для мандрівників із чітко визначеними розділами, тому розділити код для кожної області досить просто.

Я використовую імітацію простору імен та ледачу завантаження модулів відповідно до розділу сайту. На кожному завантаженні сторінки я оголошую об'єкт "vjr" і завжди завантажую набір загальних функцій (vjr.base.js). Потім кожна HTML-сторінка визначає, які модулі потрібні за допомогою простого:

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

Vjr.base.js отримує кожен gzipped з сервера та виконує їх.

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

Кожен "модуль" має таку структуру:

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

Враховуючи мої обмежені знання Javascript, я знаю, що повинні бути кращі способи управління цим, але до цих пір це для нас чудово працює.


6

Організація коду способом, орієнтованим на Jquery NameSpace, може виглядати наступним чином ... і не буде конфліктувати з іншими API Javascript, такими як 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>

Сподіваюсь, це допомагає.


Це вражає мене, як невеликого вантажу. jQuery.fnє вказівником на jQuery.prototype, тому що $()фактично повертає новий екземпляр функції конструктора jQuery. Додавання "плагіна" до jQuery означає просто розширити його прототип. Але те, що ви робите, це не те, і є більш чіткі способи досягнення того ж самого.
Адам Лассек

Я вважаю, що він просто створює статичні функції. Я пам'ятаю, як в документах jQuery бачив, що такий спосіб оголошення статичних функцій прийнятний
Алекс Гейд,

6

Хороший директор OO + MVC, безумовно, пройде довгий шлях управління складним додатком javascript.

В основному я організовую свою програму та javascript для наступного знайомого дизайну (який існує весь час від моїх робочих днів програмування до Web 2.0)

JS OO та MVC

Опис числових значень на зображенні:

  1. Віджети, що представляють погляди моєї програми. Це повинно бути розширюваним та відокремленим, завдяки чому MVC намагається досягти, а не перетворювати свій віджет у код спагетті (еквівалент у веб-додатку, що розміщує великий блок Javascript безпосередньо в HTML). Кожен віджет спілкується через інші, прослуховуючи подію, породжену іншими віджетами, таким чином зменшуючи сильну зв’язок між віджетами, що може призвести до некерованого коду (згадайте день додавання onclick скрізь, що вказує на глобальні функції в тезі сценарію? Urgh ...)
  2. Об'єктні моделі, що представляють дані, які я хочу заповнити у віджетах, передаючи назад і назад на сервер. За допомогою інкапсуляції даних у свою модель додаток стає агностиком формату даних. Наприклад: в той час, коли в Javascript ці об'єктні моделі здебільшого серіалізуються і десеріалізуються в JSON, якщо сервер якось використовує XML для зв'язку, все, що мені потрібно змінити, - це зміна рівня серіалізації / десеріалізації і не обов'язково потрібно змінювати всі класи віджетів .
  3. Класи контролерів, які керують діловою логікою та зв’язком із сервером + час від часу шаром кешування. Цей рівень управляє протоколом зв'язку з сервером і вводить необхідні дані в об'єктні моделі
  4. Класи акуратно загорнуті у відповідні простори імен. Я впевнений, що всі ми знаємо, наскільки гадкий глобальний простір імен може бути у Javascript.

Раніше я би розділяв файли на власний js і використовував звичайну практику для створення принципів ОО в JavaScript. Проблема, що я незабаром виявив, що існує кілька способів написання JS OO, і не обов’язково, що всі члени команди мають однаковий підхід. Коли команда зросла (в моєму випадку понад 15 осіб), це ускладнюється, оскільки не існує стандартного підходу для об'єктно-орієнтованого Javascript. У той же час я не хочу писати власні рамки та повторювати частину роботи, яку я впевнений, розумніші люди, ніж я вирішив.

jQuery неймовірно приємний, як Javascript Framework, і мені це подобається, проте, коли проект збільшується, я, очевидно, потребую додаткової структури для свого веб-додатка, особливо для полегшення стандартизації практики OO. Для себе, після декількох експериментів, я вважаю, що база YUI3 Base and Widget ( http://yuilibrary.com/yui/docs/widget/ та http://yuilibrary.com/yui/docs/base/index.html ) забезпечує інфраструктуру саме те, що мені потрібно. Мало причин, чому я їх використовую.

  1. Він забезпечує підтримку простору імен. Справжня потреба в ОО та акуратній організації вашого коду
  2. Він підтримує поняття класів та об'єктів
  3. Це дає засоби стандартизації для додавання змінних екземплярів до вашого класу
  4. Він акуратно підтримує розширення класу
  5. Він забезпечує конструктор і деструктор
  6. Він забезпечує прив'язку візуалізації та подій
  7. Він має базовий фреймворк віджетів
  8. Кожен віджет тепер може спілкуватися один з одним за допомогою стандартної моделі на основі подій
  9. Найголовніше, що він дає всім інженерам стандарт OO для розробки Javascript

На відміну від багатьох поглядів, мені не обов’язково вибирати між jQuery та YUI3. Ці двоє можуть мирно співіснувати. Хоча YUI3 надає необхідний шаблон OO для мого складного веб-додатку, jQuery все ще надає моїй команді просту у використанні абстракцію JS, яку ми всі любимо і знайомо.

Використовуючи YUI3, мені вдалося створити шаблон MVC, відокремивши класи, що розширюють Базу як модель, класи, які розширюють віджет як перегляд і поза курсом, у вас є класи контролерів, які здійснюють необхідні логіки та виклики на стороні сервера.

Віджет може спілкуватися між собою, використовуючи модель на основі подій та прослуховуючи подію, виконуючи необхідні завдання на основі попередньо визначеного інтерфейсу. Простіше кажучи, розміщення структури OO + MVC в JS - це радість для мене.

Просто відмова, я не працюю в Yahoo! і просто архітектор, який намагається впоратися з тим же питанням, яке постає перед початковим запитанням. Я думаю, якщо хтось знайде еквівалентну рамку ОО, це також спрацює. В основному це питання стосується і інших технологій. Дякую Богу за всіх людей, які придумали принципи ОО + MVC, щоб зробити наші дні програмування більш керованими.


5

Я використовую управління пакетами Dojo ( dojo.requireі dojo.provide) та систему класів ( dojo.declareщо також дозволяє просте багатократне успадкування), щоб модулювати всі мої класи / віджети в окремі файли. Це не лише дозує ваш код впорядкованому, але також дозволяє вам лінуватися / під час завантаження класів / віджетів.


3

Кілька днів тому хлопці в 37Signals випустили управління RTE , з поворотом. Вони створили бібліотеку, яка поєднує файли javascript, використовуючи певні команди попереднього процесора.

Я використовую його з тих пір, щоб розділити свої файли JS, а потім врешті об'єднати їх як один. Таким чином я можу відокремити проблеми і, врешті-решт, мати лише один файл, який проходить через трубу (gzipped, не менше).

У своїх шаблонах перевірте, чи перебуваєте ви в режимі розробки, і включіть окремі файли, а якщо у виробництві, включіть остаточний (який вам доведеться самостійно "скласти").


1
getprockets.org - це пряме посилання
Метт Гарднер

3

Створіть підроблені заняття та переконайтесь, що все, що можна перекинути на окрему функцію, яка має сенс, зробила так. Також переконайтеся, що коментувати багато, а не писати код спагетті, а зберігати все це в розділах. Наприклад, якийсь безглуздий код, що зображує мої ідеали. Очевидно, що в реальному житті я також пишу багато бібліотек, які в основному охоплюють їх функціональність.

$(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.
    }
};

3

Я починаю використовувати його, навіть для дуже маленьких / основних речей, і це дійсно допомагає у збереженні коду чистим та гнучким. Його варто використовувати навіть для простих маніпуляцій на JS на стороні клієнта.
Четан

Це мені подобається і використовувати в моїх програмах.
Андреас

2

Я думаю, що це пов'язано, можливо, з DDD (Design-Driven Design). Програма, над якою я працюю, хоча і не має офіційного API, але дає підказки про це за допомогою коду на стороні сервера (назви класів / файлів тощо). Озброївшись цим, я створив об’єкт верхнього рівня як контейнер для всієї проблемної області; потім я додав простору імен там, де потрібно:

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 використовували наступне

  1. Папка для всіх ваших javascript
  2. JavaScript на рівні сторінки отримує власний файл з тим же найменуванням сторінки. ProductDetail.aspx буде ProductDetail.js
  3. Всередині папки javascript для бібліотечних файлів у мене папка lib
  4. Помістіть відповідні функції бібліотеки у папку lib, яку ви хочете використовувати у всій програмі.
  5. Ajax - це єдиний JavaScript, який я переміщу за межі папки javascript і отримує його власну папку. Потім я додаю дві підпапки клієнта та сервера
  6. Клієнтська папка отримує всі файли .js, тоді як папка сервера отримує всі файли на стороні сервера.

Приємно для організації файлів. Я роблю це з кодом. Але врешті-решт я збираю свій код у ... скажімо, dll. Вам це потрібно і з javascript, інакше ви запитаєте 15 js-файлів на сторінку.
graffic

Немає нічого поганого в тому, щоб запитувати 15 JS-файлів на сторінку. Ваш браузер все одно буде кешувати їх для подальших запитів.
Marnen Laibow-Koser

@ MarnenLaibow-Koser Єдине питання із запитом на 15 файлів JS на сторінці - це кількість запитів HTTP, якими браузер може обробитись одночасно. Таким чином, поєднання їх в один файл дозволяє браузеру одночасно запитувати інші необхідні файли.
iwasrobbed

Це правда, але після перших кількох звернень вони будуть знаходитись у кеші браузера, тому вони не потребуватимуть HTTP-з'єднань.
Marnen Laibow-Koser

2

Я використовую цю дрібницю. Це дає вам директиву "включити" для шаблонів JS та HTML. Це повністю викреслює безлад.

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

Ви можете використовувати jquery mx (використовується в javascriptMVC) - це набір сценаріїв, що дозволяє використовувати моделі, представлення даних та контролери. Я використовував це в проекті і допоміг мені створити структурований javascript з мінімальними розмірами скриптів через стиснення. Це приклад контролера:

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

Ви також можете використовувати лише сторону контролера jquerymx, якщо вас не цікавлять деталі перегляду та моделі.


1

Ваше запитання - це питання, яке набридло мені наприкінці минулого року. Різниця - передача коду новим розробникам, які ніколи не чули про приватні та публічні методи. Мені довелося побудувати щось просте.

Кінцевим результатом став невеликий (близько 1 КБ) фреймворк, який переводить об'єктні літерали в jQuery. Синтаксис візуально простіше сканувати, і якщо ваш js зростає дійсно великим, ви можете писати запити для багаторазового використання, щоб знайти такі речі, як використовувані селектори, завантажені файли, залежні функції тощо.

Опублікувати тут невелику рамку недоцільно, тому я написав допис у блозі з прикладами (Моє перше. Це була пригода!). Ви можете поглянути.

Для будь-яких інших, хто має декілька хвилин, щоб перевірити це, я дуже вдячний за відгук!

FireFox рекомендується, оскільки він підтримує toSource () для прикладу запиту об'єкта.

Ура!

Адам


0

Я використовую користувальницький сценарій, натхненний поведінкою Бен Нолана (на жаль, я вже не можу знайти поточне посилання на це, щоб зберігати більшість моїх обробників подій. Такі обробники подій, наприклад, ініціюються елементами className або Id. Приклад:

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

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

});

Мені подобається включати більшість моїх бібліотек Javascript, за винятком тих, що містять глобальну поведінку. Я використовую помічник заміщає Zend Framework в headScript () для цього, але ви також можете використовувати Javascript , щоб завантажити інші сценарії на льоту з Ajile , наприклад.


Це те, що ви шукали? koders.com/javascript/…
DOK

Так, це один! :) Схоже, що код за посиланням є доволі новим, ніж версія, на яку я надихнувся. Дякуємо за ваші зусилля!
Арон Ротвевель

0

Ви не згадуєте, що таке мова вашого сервера. Або, що більш доречно, яку рамку ви використовуєте (якщо така є) на стороні сервера.

IME, я організовую речі на стороні сервера і нехай це все виштовхується на веб-сторінку. В основу покладено завдання організувати не тільки JS, який повинна завантажувати кожна сторінка, а й фрагменти JS, які працюють з генерованою розміткою. Такі фрагменти, як правило, не хочуть випускатись не один раз - саме тому вони заносяться в рамки для цього коду, щоб вирішити цю проблему. :-)

Для кінцевих сторінок, які мають випромінювати власний JS, я зазвичай вважаю, що в створеній розмітці є логічна структура. Такі локалізовані JS часто можуть бути зібрані на початку та / або в кінці такої структури.

Зауважте, що жодне з цього не звільняє вас від написання ефективного JavaScript! :-)


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.