Общепринятые передовые практики организации кода в JavaScript

Поскольку JavaScript-фреймворки, такие как jQuery, делают клиентские веб-приложения богаче и функциональнее, я начал замечать одну проблему ...

Как, черт возьми, вы все это организовываете?

  • Поместите все ваши обработчики в одно место и напишите функции для всех событий?
  • Создать функцию / классы, чтобы обернуть всю вашу функциональность?
  • Пишите как сумасшедший и просто надеетесь, что у вас все получится?
  • Сдаться и начать новую карьеру?

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

Есть ли какие-либо общие рекомендации по тому, как лучше всего сохранить ваши файлы .js такими же красивыми и аккуратными, как и остальная часть вашего приложения? Или все дело в IDE? Есть ли лучший вариант?


РЕДАКТИРОВАТЬ

Этот вопрос был задуман, чтобы больше касаться организации кода, а не организации файлов. Было несколько действительно хороших примеров объединения файлов или разделения содержимого.

Мой вопрос: каков общепринятый в настоящее время наилучший способ организации вашего реального кода? Каков ваш способ или даже рекомендуемый способ взаимодействия с элементами страницы и создания повторно используемого кода, который не конфликтует друг с другом?

Некоторые люди указали пространства имен, что является хорошей идеей. Какие есть другие способы, более конкретно работать с элементами на странице и поддерживать порядок и аккуратность кода?

кто-то, кто на самом деле нашел время, чтобы рассказать о самой организации кода, а не «просто» о том, какой инструмент он использует для объединения и сжатия своих файлов JS: stackoverflow.com/questions/16736483/…

Adrien Be 13.11.2014 18:17
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
566
1
50 144
28

Ответы 28

Вы можете разбить свои скрипты на отдельные файлы для разработки, а затем создать «релизную» версию, в которой вы скомкаете их все вместе и запустите на ней Компрессор YUI или что-то подобное.

Иногда встречаются ненужные скрипты javascript. Отправлять их клиенту расточительно. Я думаю, что лучше отправлять только то, что нужно. Конечно, для веб-приложения, которое используется весь день, например приложения для интрасети, может быть лучше отправить весь пакет сразу при загрузке первой страницы.

DOK 29.10.2008 20:52

Компиляция @DOK должна включать удаление неиспользуемого материала.

aehlke 13.12.2010 21:34

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

jamiebarrow 25.08.2011 15:20

Несколько дней назад ребята из 37Signals выпустил элемент управления RTE, с изюминкой. Они сделали библиотеку, которая связывает файлы javascript с помощью команд препроцессора.

С тех пор я использую его, чтобы разделить свои JS-файлы, а затем, в конце концов, объединить их как один. Таким образом, я могу разделить проблемы и, в конце концов, получить только один файл, который проходит через конвейер (сжатый с помощью gzip, не меньше).

В своих шаблонах проверьте, находитесь ли вы в режиме разработки, и включите отдельные файлы, а если в производстве, включите последний (который вам придется «собрать» самостоятельно).

getsprockets.org - прямая ссылка
Matt Gardner 01.08.2009 05:53

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

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

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

});

Мне нравится включать большинство моих библиотек Javascript на лету, за исключением тех, которые содержат глобальное поведение. Я использую для этого Помощник-заполнитель headScript () Zend Framework, но вы также можете, например, используйте javascript для загрузки других скриптов на лету с Аджиле.

Это то, что ты искал? koders.com/javascript/…

DOK 29.10.2008 20:59

Ага, это тот самый! :) Похоже, что код за ссылкой довольно новее, чем версия, на которую я был вдохновлен. Спасибо за ваши усилия!

Aron Rotteveel 09.12.2008 12:47

Мой босс до сих пор говорит о тех временах, когда они писали модульный код (язык C), и жалуется на то, какой паршивый код сейчас! Говорят, что программисты могут писать сборку в любом фреймворке. Всегда есть стратегия преодоления организации кода. Основная проблема заключается в парнях, которые относятся к java-скрипту как к игрушке и никогда не пытаются его изучить.

В моем случае я пишу файлы js на основе темы пользовательского интерфейса или экрана приложения с правильным init_screen (). Используя правильное соглашение об именах идентификаторов, я убеждаюсь, что на уровне корневого элемента нет конфликтов пространства имен. В ненавязчивом window.load () я связываю вещи на основе идентификатора верхнего уровня.

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

Было бы намного лучше, если бы в 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
            }
    };
})();

Я помещаю разные «пространства имен», а иногда и отдельные классы в отдельные файлы. Обычно я начинаю с одного файла, и по мере того, как класс или пространство имен становятся достаточно большими, чтобы это гарантировать, я выделяю его в отдельный файл. Использование инструмента для объединения всех ваших файлов для производства также является отличной идеей.

Я обычно называю это «крокфордским способом». +1 от меня

Matt Briggs 12.08.2010 05:11

Можно даже пойти немного дальше. См. Эту ссылку: wait-till-i.com/2007/08/22/…

MKroehnert 16.08.2010 16:31

@MattBriggs иначе называется module pattern и основан на IIFE pattern.

Adrien Be 13.11.2014 17:26

Вам не нужно как-то экспортировать классы? Как объект создается извне такого модуля? Или в возвращаемом объекте должен быть метод createNewSomething(), чтобы создание объекта происходило исключительно внутри модуля? Хм ... Я ожидал, что классы (конструкторы) видны извне.

robsch 04.07.2016 10:35

@robsch Его пример не принимает никаких параметров, но большинство из них. Посмотрите мой пример, как это обычно делается (TypeScript, но на 99% то же самое): repl.it/@fatso83/Module-Pattern-in-TypeScript

oligofren 21.06.2019 11:32

Я создаю синглтоны для всего, что мне действительно не нужно создавать несколько раз на экране, - классы для всего остального. И все они помещаются в одно и то же пространство имен в один файл. Все прокомментировано и спроектировано с использованием UML, диаграмм состояний. Код javascript не содержит html, поэтому нет встроенного javascript, и я предпочитаю использовать jquery, чтобы минимизировать проблемы с кроссбраузерностью.

хорошие комментарии - КЛЮЧЕВЫЕ - Я рад, что вы сказали это, поэтому мне не пришлось. Я бы добавил последовательные соглашения об именах, какую-то легко понятную стратегию организации для переменных & amp; функций, и, как вы упомянули, разумное использование классов по сравнению с одиночными.

matt lohkamp 05.11.2008 15:53

Нет. Если вам нужны комментарии, ваш код обычно недостаточно читается. Стремитесь писать код, не нуждающийся в комментариях.

Marnen Laibow-Koser 14.08.2011 07:43

Кроме того, если вам нужен UML и диаграммы состояний, это, вероятно, означает, что ваша архитектура недостаточно ясна из кода. Голосование против.

Marnen Laibow-Koser 15.02.2013 21:40

@Marnen Хорошо написанные проекты включают комментарии, описывающие ПОЧЕМУ, не обязательно ЧТО. Код уже описывает ЧТО, но часто вам нужно что-то описать ПОЧЕМУ. Голосование за.

Cypher 08.04.2014 01:39

@Cypher Хорошо написанные проекты имеют достаточно ясный код, поэтому вы обычно можете сказать «почему», а не только «что». Я бы не поверил, что комментарий скажет мне «почему», потому что у меня нет гарантии, что он синхронизируется с кодом. Пусть сам код документирует.

Marnen Laibow-Koser 29.05.2014 19:16

Вы не упоминаете, какой у вас язык на стороне сервера. Или, что более уместно, какую структуру вы используете - если таковая имеется - на стороне сервера.

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

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

Обратите внимание, что все это не освобождает вас от написания эффективного JavaScript! :-)

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

Идея состоит в том, чтобы использовать Звездочки (от WysiHat), чтобы объединить несколько сценариев JavaScripts в один файл, проверить синтаксис объединенного файла с помощью JSLint и минимизировать его с помощью YUI Compressor перед распространением.

Предпосылки

  • Среда выполнения Java
  • рубин и грабли драгоценный камень
  • Вы должны знать, как поместить JAR в Путь к классам

Теперь сделай

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

Теперь создайте файл с именем «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-кода

При объединении источников

Используя 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
})();

А потом...

Взгляните на Rakefile, поставляемый с WysiHat, чтобы настроить автоматическое модульное тестирование. Хорошая штука :)

А теперь ответ

Это не очень хорошо отвечает на исходный вопрос. Я знаю и сожалею об этом, но я разместил это здесь, потому что надеюсь, что кому-то будет полезно организовать беспорядок.

Мой подход к проблеме состоит в том, чтобы делать как можно больше объектно-ориентированного моделирования и разделять реализации по разным файлам. Тогда обработчики должны быть как можно короче. Пример с синглтоном List тоже хорош.

И пространства имен ... ну, их можно имитировать более глубокой структурой объектов.

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

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

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

Я не большой поклонник имитаций, но это может быть полезно, если у вас есть много объектов, которые вы хотели бы переместить за пределы глобальной области видимости.

Мне удалось успешно применить Шаблон модуля Javascript к приложению Ext JS на моей предыдущей работе. Он предоставил простой способ создать красиво инкапсулированный код.

Я стараюсь избегать включения 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>');
  //...
};

Используя этот подход, я создал несколько довольно сложных приложений.

Я считаю, что использование $ в качестве префикса имени переменной - более распространенная практика, но я могу ошибаться. Итак, $s = $('...') вместо jS = $('...'), я полагаю, это вопрос предпочтений. Это интересно, поскольку венгерские обозначения считаются запахом кода. Странно, насколько некоторые из моих соглашений / предпочтений в отношении кода JavaScript отличаются от моих соглашений о кодировании C# / Java.

jamiebarrow 25.08.2011 15:11

@jamie В данном случае это не запах кода, это как раз один из немногих случаев, когда венгерский - это хорошо. Вы можете прочитать это.

Dan Abramov 02.10.2011 23:41

@DanAbramov спасибо за ссылку. Я действительно должен прочитать все блоги Джоэла, он так хорошо объясняет. Определенно заслуживает той славы / репутации, которые у него есть. С этого момента я буду называть Systems Hungarian запахом кода, а Apps Hungarian - практикой :)

jamiebarrow 13.10.2011 14:20

Я думаю, что в мире C# это также могла бы быть отличная статья для продвижения использования var, теперь, когда я думаю об этом. Большинство аргументов против использования var заключаются в том, что вы не можете быть уверены в «типе» того, что возвращается, но я думаю, что аргумент должен быть скорее против незнания «класса» возвращаемого. Если вы используете Apps Hungarian, у вас не должно быть этого беспокойства, тогда ... интересно.

jamiebarrow 13.10.2011 14:22

Приставка $ вообще бесполезна. Венгерские приложения здесь не подходят, потому что JS имеет систему типов, которая не позволит вам делать неправильные вещи с вашими объектами jQuery. Приложения на венгерском языке желательны только тогда, когда система типов не может сделать вашу проверку за вас.

Marnen Laibow-Koser 15.02.2013 21:37

@Marnen: Я понимаю вашу точку зрения, но она не бесполезна в качестве руководства для программиста. Префикс $ напоминает мне, что это такое, когда я позже читаю мой код, и, таким образом, помогает быстрее понять.

Sean 19.06.2013 00:28

@ Шон Но это все еще плохая идея. Вы не должны выполнять ту работу, которую уже может делать переводчик. У интерпретатора есть надежная система типов, поэтому положитесь на нее. Вы не пишете nPixels или strName, поэтому не пишите $element. Более того, является бесполезен в качестве ориентира: ничто не мешает вам писать var $element = 3.

Marnen Laibow-Koser 25.06.2013 23:23

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

Идея хорошо используется в других языках для разработки графического интерфейса. Когда где-то в вашем коде происходит что-то существенное, вы публикуете глобальное синтетическое событие, на которое могут подписаться другие методы в других объектах. Это дает отличное разделение объектов.

Я думаю, что в Dojo (и Prototype?) Есть встроенная версия этой техники.

см. также Что такое сигналы и слоты?

Я сделал это в jQuery. JS имеет встроенную модель событий, поэтому вам действительно не нужна большая поддержка фреймворка.

Marnen Laibow-Koser 15.02.2013 21:39

В Dojo с самого начала была модульная система. Фактически, он считается краеугольным камнем Додзё, клеем, который скрепляет все это:

Использование модулей Dojo позволяет достичь следующих целей:

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

Ленивая загрузка нужного кода по запросу. Google делает что-то подобное со своим google.loader

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

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

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

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

Каждый «модуль» имеет такую ​​структуру:

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, я знаю, что должны быть лучшие способы справиться с этим, но до сих пор он отлично работает для нас.

«Пишите как сумасшедший и просто надейтесь, что это сработает к лучшему?» - я видел такой проект, который разрабатывали и поддерживали всего 2 разработчика, огромное приложение с большим количеством кода javascript. Вдобавок ко всему, были разные ярлыки для каждой возможной функции jquery, о которой вы только можете подумать. Я предложил организовать код в виде подключаемых модулей, поскольку это эквивалент класса, модуля, пространства имен и всей вселенной в jquery. Но все стало намного хуже, теперь они начали писать плагины, заменяющие каждую комбинацию из 3 строк кода, используемых в проекте. Лично я считаю, что jQuery - это дьявол, и его не следует использовать в проектах с большим количеством javascript, потому что он побуждает вас лениться и не думать об организации кода каким-либо образом. Я бы предпочел прочитать 100 строк javascript, чем одну строку с 40 связанными функциями jQuery (я не шучу). Вопреки распространенному мнению, очень легко организовать код javascript в эквивалентах пространств имен и классов. Вот что делают YUI и Dojo. Вы можете легко свернуть свою собственную, если хотите. Я считаю, что подход YUI намного лучше и эффективнее. Но обычно вам нужен хороший редактор с поддержкой сниппетов, чтобы компенсировать соглашения об именах YUI, если вы хотите написать что-нибудь полезное.

Я согласен с вами в отношении действительно длинных, связанных команд, но одна из лучших частей jQuery заключается в том, что он сохраняет весь Javascript вне HTML. Вы можете настроить обработчики событий для всех ваших элементов без «необходимости» добавлять идентификаторы или события <whatever> на ваших элементах. Как всегда, чрезмерное использование любого инструмента - это плохо ...

hugoware 23.12.2008 16:07

Я работал над огромными, хорошо организованными проектами на jQuery. Я не знаю, почему вы думаете, что это мешает организации.

Marnen Laibow-Koser 14.08.2011 07:41

Я думаю, что это связано, возможно, с DDD (Domain-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.info( s );
        }
        return this;
    }
})(App);

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

Организация вашего кода в стиле NameSpace, ориентированном на JQuery, может выглядеть следующим образом ... и не будет конфликтовать с другими 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.info('Hello');
    };

    Acme.sayBye = function()
    {
        console.info('Good Bye');
    };
})(AcmeJQ);

// Usage
//          Acme.sayHi();
// or
// <a href = "#" onclick = "Acme.sayHi();">Say Hello</a>


</script>

Надеюсь это поможет.

Мне это кажется небольшой грузоподъемностью. jQuery.fn - это указатель на jQuery.prototype, потому что $() фактически возвращает новый экземпляр функции конструктора jQuery. Добавление «плагина» к jQuery означает простое расширение его прототипа. Но то, что вы делаете, не является этим, и есть более чистые способы сделать то же самое.

Adam Lassek 27.01.2011 22:14

Я считаю, что он просто создает статические функции. Я помню, как видел в документации jQuery, что такой способ объявления статических функций приемлем.

Alex Heyd 30.03.2011 00:30

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

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

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

Проверьте JavasciptMVC.

Ты можешь :

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

  • сжать весь код в один производственный файл

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

  • создавать и запускать модульные тесты

  • и многое другое ...

Лучше всего то, что он использует jQuery, поэтому вы также можете воспользоваться другими плагинами jQuery.

Да, я использовал jmvc, и он довольно хорош - хотя документы могли бы быть лучше

meouw 05.02.2010 17:51

Для организации 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 23.08.2010 18:24

Нет ничего плохого в том, чтобы запрашивать 15 файлов JS на страницу. Ваш браузер в любом случае кэширует их для последующих запросов.

Marnen Laibow-Koser 14.08.2011 07:45

@ MarnenLaibow-Koser Единственная проблема с запросом 15 файлов JS на странице - это то, сколько HTTP-запросов браузер может обрабатывать за раз. Таким образом, объединение их в один файл позволяет браузеру одновременно запрашивать другие необходимые файлы.

iwasrobbed 11.10.2011 07:47

Это правда, но после первой пары обращений они будут в кеше браузера, поэтому им не потребуются HTTP-соединения.

Marnen Laibow-Koser 11.10.2011 21:43

Пользуюсь этой вещицей. Он дает вам директиву include для шаблонов 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.
        });
    }
});

Используйте шаблоны наследования для организации больших приложений jQuery.

Я начинаю использовать его даже для очень маленьких / простых вещей, и это действительно помогает сохранять код чистым и гибким. Его стоит использовать даже для простых манипуляций с JS на стороне клиента.

Chetan 29.03.2011 06:46

Это мне нравится, и я использую его в своих приложениях.

Andreas 23.01.2013 17:57

Ваш вопрос мучил меня в конце прошлого года. Отличие - передача кода новым разработчикам, которые никогда не слышали о частных и публичных методах. Пришлось построить что-то простое.

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

Публиковать здесь небольшой фреймворк непрактично, поэтому я написал сообщение в блоге с примерами (Мой первый. Это было приключение!). Приглашаем взглянуть.

Если у вас есть несколько минут, чтобы проверить это, я буду очень признателен за обратную связь!

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

Ваше здоровье!

Адам

Я удивлен, что никто не упомянул фреймворки MVC. Я использовал Backbone.js для модуляции и разделения моего кода, и это было бесценно.

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

Вы можете использовать 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, если вас не интересуют части вида и модели.

Хороший принцип OO + MVC определенно будет иметь большое значение для управления сложным приложением javascript.

В основном я организовываю свое приложение и javascript в соответствии со следующим знакомым дизайном (который существует еще со времен моего программирования для настольных компьютеров до Web 2.0)

JS OO and MVC

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

  1. Виджеты, представляющие представления моего приложения. Он должен быть расширяемым и аккуратно отделенным, что должно привести к хорошему разделению, которого пытается достичь MVC, вместо того, чтобы превращать мой виджет в спагетти-код (эквивалент в веб-приложении размещения большого блока Javascript непосредственно в HTML). Каждый виджет обменивается данными через других, прослушивая событие, генерируемое другими виджетами, тем самым уменьшая сильную связь между виджетами, которая может привести к неуправляемому коду (помните день добавления onclick повсюду, указывающего на глобальные функции в теге скрипта? Ура ...)
  2. Объектные модели, представляющие данные, которые я хочу заполнить в виджетах и ​​передать на сервер туда и обратно. Инкапсулируя данные в своей модели, приложение становится агностиком формата данных. Например: в то время как естественно в Javascript эти объектные модели в основном сериализованы и десериализованы в JSON, если сервер каким-то образом использует XML для связи, все, что мне нужно изменить, это изменить уровень сериализации / десериализации и не обязательно менять все классы виджетов. .
  3. Классы контроллеров, которые управляют бизнес-логикой и связью с сервером + иногда кэширующий слой. Этот уровень управляет протоколом связи с сервером и помещает необходимые данные в объектные модели.
  4. Классы аккуратно обернуты в соответствующие им пространства имен. Я уверен, что все мы знаем, насколько неприятным может быть глобальное пространство имен в Javascript.

Раньше я разделял файлы на собственные js и использовал обычную практику для создания принципов объектно-ориентированного программирования в Javascript. Проблема, которую я вскоре обнаружил, заключается в том, что существует несколько способов написания JS OO, и не обязательно, чтобы все члены команды придерживались одного и того же подхода. По мере того, как команда увеличивалась (в моем случае более 15 человек), это усложнялось, поскольку не было стандартного подхода для объектно-ориентированного Javascript. В то же время я не хочу писать свой собственный фреймворк и повторять некоторые работы, которые, я уверен, более умные люди, чем я решил.

jQuery невероятно хорош, как Javascript Framework, и мне он нравится, однако по мере того, как проект становится больше, мне явно нужна дополнительная структура для моего веб-приложения, особенно для облегчения стандартизации практики объектно-ориентированного программирования. Что касается себя, то после нескольких экспериментов я обнаружил, что инфраструктура YUI3 Base и Widget (http://yuilibrary.com/yui/docs/widget/ и http://yuilibrary.com/yui/docs/base/index.html) обеспечивает именно то, что мне нужно. Несколько причин, почему я их использую.

  1. Он обеспечивает поддержку пространства имен. Реальная потребность в объектно-ориентированном дизайне и аккуратной организации вашего кода
  2. Он поддерживает понятие классов и объектов.
  3. Это дает стандартизованные средства для добавления переменных экземпляра в ваш класс.
  4. Он аккуратно поддерживает расширение класса
  5. Он предоставляет конструктор и деструктор
  6. Он обеспечивает привязку рендеринга и событий
  7. Имеет базовую структуру виджетов
  8. Каждый виджет теперь может взаимодействовать друг с другом, используя стандартную модель, основанную на событиях.
  9. Самое главное, это дает всем инженерам ОО-стандарт для разработки Javascript.

В отличие от многих представлений, мне не обязательно выбирать между jQuery и YUI3. Эти двое могут мирно сосуществовать. В то время как YUI3 предоставляет необходимый объектно-ориентированный шаблон для моего сложного веб-приложения, jQuery по-прежнему предоставляет моей команде простую в использовании абстракцию JS, которую мы все полюбили и с которой знакомы.

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

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

Просто отказ от ответственности, я не работаю в Yahoo! и просто архитектор, который пытается справиться с той же проблемой, что и исходный вопрос. Я думаю, что если кто-нибудь найдет эквивалентную объектно-ориентированную структуру, это тоже сработает. В принципе, этот вопрос касается и других технологий. Слава Богу за всех, кто придумал OO Principles + MVC, чтобы сделать наши дни программирования более управляемыми.

Кодовая организация требует принятия соглашений и стандартов документации:
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;
    ...
};


Это всего лишь несколько советов, но они очень помогли в организации кода. Помните, чтобы добиться успеха, вам нужна дисциплина!

Другие вопросы по теме