Приложение для управления данными, основанное на Javascript-кодах

В настоящее время я работаю над интерфейсом среднего/крупномасштабного управляемого ASP.NET-приложения ASP.NET, и у меня есть некоторые сомнения относительно правильного кода-организации/шаблона проектирования следовать. Веб-приложение создается несколькими страницами, содержащими многие виджеты Kendo UI MVC, определенные с помощью шаблона Razor.

Для тех, кто не знаком с Kendo, синтаксис бритвы переводится в Javascript как следующий фрагмент: Kendo server side-wrappers

Я определил внутри папки Script две основные папки, и я структурировал файлы js следующим образом:

  • shared//Содержит общие файлы js -file1.js -file2.js

  • pages//Один файл на страницу

    • page1.js
    • page2.js
    • ...
    • Ticket.js//страница 4:)

Каждый js файл представляет собой отдельный модуль, определенный со следующим шаблоном:
Примечание: функция Inside init регистрирует каждую функцию обратного вызова в событиях окна, а иногда и в блоке $(document).ready(function(){}).

;(function () {
    "use strict";

    function Ticket(settings) {
        this.currentPageUrls = settings.currentPageUrls;
        this.currentPageMessages = settings.currentPageMessages;
        this.currentPageEnums = settings.currentPageEnums;
        this.currentPageParameters = settings.currentPageParameters;         


        this.gridManager = new window.gridManager(); //usage of shared modules

        this.init();
    }

    Ticket.prototype.init = function () {           

            $("form").on("submit", function () {
                $(".window-content-sandbox").addClass("k-loading");
            });

            ...
    }    

    Ticket.prototype.onRequestStart = function (e) {

        ...
    }

    //private functions definition
    function private(a, b, c){

    }

    window.Ticket = Ticket;
}());   

Как только мне понадобятся функции Javascript, определенные в модуле, я включаю связанный файл Javascript на странице. Объект моего объекта хранится внутри переменной и, кроме того, функция привязана к событию виджета (см. OnRequestStart).

HTML/JAVASCRIPT

@(Html.Kendo().DropDownList()
      .Name("Users")
      .DataValueField("Id")
      .DataTextField("Username")
      .DataSource(d => d.Read(r => r.Action("UsersAsJson", "User"))
                        .Events(e => e.RequestStart("onRequestStart"))))



var settings = {};

var ticket = new window.Ticket(settings);

function onRequestStart(e){
    ticket.onRequestStart(e);
}

Я чувствую, что мой шаблон дизайна может быть недружелюбным для другого front-end delevoper, как и я, главным образом потому, что я решил не реализовывать модули Javascript внутри плагина JQuery.

Первый. Я делаю все неправильно?
Второй, мой шаблон дизайна подходит для тестовой среды Javascript?
Третий, которые являются обязательными сценариями для JQuery-плагинов?

Update

Добавлен вывод Javascript с помощью вышеупомянутого синтаксиса Razor.

Фрагмент кода

Ответы

Ответ 1

Структура папок

В терминах функциональности (совместно используемых) и модулей (модульный подход) код разработки или приложения должен представлять собой то, что вы можете встретить в HTML. Простой ctrl + f над вашим решением должен дать все возможные изменения. Из этого опыта на протяжении многих лет я лично предпочитаю его разделять:

  • приложение (код приложения)
    • классы (многоразовые)
    • модули (singleton)
  • lib (менеджер пакетов /grunt/ gulp/...)
    • jquery (правильные имена библиотек /unminified dist файл или корневой файл)
    • кэндо

Имена файлов

Представление того, что что-то делает, и возможность повторного использования его в мгновение ока - это то, что сократит время разработки. Выбор правильных имен имеет значение, поскольку я уверен, что вы знаете. Мои имена файлов всегда начинаются с namespace, как правило, коротким, за которым следует многоразовый термин "поиск":

  • приложение/прототипы
    • ns.calendar.js(несколько конфигураций)
    • ns.maps.js(комбинации или отдельные приложения)
    • ns.places.js(формы или надстройки карты)
    • ns.validation.js(несколько форм и общая обработка)
  • приложение/синглтоны
    • ns.cookiebox.js(одиночная конфигурация)
    • ns.socialmedia.js(одна конфигурация)
    • ns.dom.js(предоставляет место для коррекции dom, события глобального изменения размера, небольшие виджеты,...)

Чтобы добавить то, что вы назвали общим, это функциональность, которая должна быть глобальной. Отличным примером будет использование библиотеки подчеркивания. Или создайте набор функций (обнаружение устройства, дроссельная заслонка, помощники в целом) самостоятельно для повторного использования во всех проектах = > ns.fn.js Поскольку вы добавляете их только один раз на протяжении всего пространства имен, он также создается как singleton и может быть добавлен в папку модулей или непосредственно в корне приложения.

Как последнее добавление файла загрузчика для запуска вашей точки управления = > ns.load.js в корне приложения. Этот файл содержит одно событие готовности DOM для привязки протоипов и модулей.

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

Структура файла

Честно говоря, мне больше нравится Tip 1 of @TxRegex, с небольшим добавлением для связывания пространства имен и передачи его из файла в файл по мере его загрузки.

Основной принцип: IIFE привязан к окну

window.NameSpace = (function($, ns){
    'strict'
    function private(){}
    var x;
    ns.SearchTerm = {};
    return ns;
}(window.jQuery, window.NameSpace || {}));

Для более примера кода я хотел бы указать github account.

Пакетирование

Попробуйте создать единый связанный и мини файл из lib в приложение, загруженный в head on async для выпуска продукции. Используйте разделенные и unminified файлы script на defer для целей разработки и отладки. Вы должны избегать встроенного script с глобальными зависимостями во всем проекте, если вы это сделаете.

  • путь к js/lib/**/*. js (обычно разделенный для сохранения последовательного порядка)
  • путь к js/app/ns.load.js
  • путь к js/app/ns.fn.js
  • путь к js/app/**/*. js (автоматическое обновление пакета)

Выход = > ns.bundle.js      = > ns.bundle.min.js

Таким образом, вы избежите проблем с блокировкой блокировки в JavaScript и ускорите процесс загрузки, что, в свою очередь, повысит SEO. Также позволяет сочетать функциональность для мобильных макетов и макетов рабочего стола "на лету" без проблем с памятью или резкого поведения. Очень хорошо зарекомендовал себя и генерирует небольшие накладные расходы при вызове экземпляров из файла загрузчика. Поскольку один пучок будет кэшироваться на всех ваших страницах, все зависит от того, сколько зависимостей или библиотек вы можете вырезать из пакета. Идеально для средних и крупных проектов, где код может быть общим и подключен к различным проектам.

Дополнительная информация об этом в другом сообщении.

Заключение

Во-первых, я делаю все неправильно?

  • Совсем нет, ваш модульный подход выглядит нормально...
  • Отсутствует глобальное пространство имен, чего трудно избежать, по крайней мере, одним. Вы создаете один для каждого модуля, но лучше всего группировать их под одним пространством имен, чтобы вы могли отличить код библиотеки от кода приложения в объекте окна.
  • Kendo, похоже, создает встроенные скрипты? Вы не можете противостоять стороне сервера размещения?

Во-вторых, мой шаблон дизайна подходит для тестовой среды Javascript?

  • За исключением экземпляров Kendo, вы можете добавить слой для целей тестирования. Помните, что если jQuery является вашей зависимой линией, вам нужно будет отложить ее загрузку. В противном случае = > jQuery is undefined
  • Исключить зависимости Kendo из пакета, если вы не можете управлять встроенным script. Перейдите к пакетному решению </body>.

В-третьих, которые являются обязательными сценариями для JQuery-плагинов?

  • модульный подход
  • настраиваемый подход для нескольких экземпляров (подсказка: перемещение всех строк из вашей логики, см., как Kendo использует объектные литералы)
  • менеджер пакетов, чтобы отделить "мусор" от "золотого"
  • grunt/ gulp/... настройка для разделения scss и css из js
  • попробуйте выполнить привязку атрибута данных, поэтому после того, как все будет записано, вы настраиваете новые экземпляры через HTML.

Запишите один раз, при необходимости легко адаптируйте и настройте много!

Ответ 2

Организация и шаблон кажутся прекрасными, но у меня есть несколько советов:

Совет 1:

Вместо того, чтобы устанавливать определенные глобальные переменные в вашем модуле, возможно, вы могли бы вернуть объект. Поэтому вместо этого:

;(function () {
"use strict";

    function Ticket(settings) {
        console.log("ticket created", settings);
    }
    ...
    window.Ticket = Ticket;
}()); 

Вы бы сделали это:

;window.Ticket = (function () {
"use strict";

    function Ticket(settings) {
        console.log("ticket created", settings);
    }
    ...
    return Ticket;
}()); 

Причиной этого является возможность взять код модуля и при необходимости присвоить ему другое имя глобальной переменной. Если есть конфликт имен, вы можете переименовать его в MyTicket или что-то другое без фактического изменения внутреннего кода модуля.

Совет 2:

Забудьте подсказку 1, глобальные переменные воняют. Вместо того, чтобы создавать отдельную глобальную переменную для каждого типа объекта, почему бы не создать диспетчер объектов и использовать одну глобальную переменную для управления всеми вашими объектами:

window.myCompany = (function () {
    function ObjectManager(modules) {
        this.modules = modules || {};
    }

    ObjectManager.prototype.getInstance = function(type, settings) {
        if (!type || !this.modules.hasOwnProperty(type)) {
            throw "Unrecognized object type:";
        }
        return new this.modules[type](settings);
    };

    ObjectManager.prototype.addObjectType = function(type, object) {
        if (!type) {
            throw "Type is required";
        }
        if(!object) {
            throw "Object is required";
        }
        this.modules[type] = object;
    };

    return new ObjectManager();
}());

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

;(function () {
"use strict";

    function Ticket(settings) {
        console.log("ticket created", settings);
    }
    ...
    window.myCompany.addObjectType("Ticket", Ticket);
}()); 

Теперь вы можете легко получить экземпляр для каждого типа объекта, например:

var settings = {test: true};
var ticket = window.myCompany.getInstance("Ticket", settings);

И вам остается только одна глобальная переменная.

Ответ 3

Вы можете попробовать разделить ваши файлы в разных компонентах, поскольку каждый компонент имеет папку.

например: страница 1 содержит прямоугольники, поэтому вы создаете прямоугольник для вызова папки внутри этой папки, вы создаете 3 файла rectangle.component.html, rectangle.component.css, rectangle.component.js(необязательный rectangle.spec.js для тестирование).

app
└───rectangle
        rectangle.component.css
        rectangle.component.html
        rectangle.component.js

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

Хороший способ изолировать переменные и выполнить в нужном месте - это использовать маршрутизатор в основном, что он проверяет на url и выполняет часть кода, который вы назначаете на эту страницу

надеюсь, что это поможет, дайте мне знать, если вам нужна дополнительная помощь.