Tworzenie luźno połączonej i wielostronicowej aplikacji JS przy użyciu Core ( Mediator) / Sandbox(Fasada) / Module pattern - porady?

Buduję wielostronicową aplikację javascript. Dużo czytałem o wzorcach projektowych i tworzeniu aplikacji za pomocą podejścia Core/Fasada / moduł w / luźnym połączeniu (pub / sub scribing do zdarzeń).

Mam całkiem dobry system, który minimalizuje i łączy wszystkie moje pliki modułów i powiązane zależności w jeden zewnętrzny plik javascript podczas wdrażania. Minimalizacja dodatkowych żądań HTTP dla mojej aplikacji jest celem projektowym - dlatego nie jestem zbyt zainteresowany AMD (definicja modułu asynchronicznego).

Używam wytycznych nakreślonych w prezentacji Mikołaja Zakasa, Skalowalna Architektura Aplikacji JavaScript

Http://www.youtube.com/watch?v=vXjVFPosQHw

&&

Addy Osmani ' S Patterns For Large-Scale JavaScript Application Architecture http://addyosmani.com/largescalejavascript/

&&

Ten poradnik premium, autorstwa Andrew Burgessa z Nettuts, pisząc Modular JavaScript http://marketplace.tutsplus.com/item/writing-modular-javascript/128103/?ref=addyosmani&ref=addyosmani&clickthrough_id=90060087&redirect_back=true

Moje pytanie to porada jak zarządzać różnymi stronami tej aplikacji i powiązanymi z nimi modułami. Używam również klasy routerów Backbonejs w / ballupton ' S History.biblioteka js do manipulowania API historii/stanu HTML5 i dynamicznego ładowania stron bez odświeżania przy zachowaniu kompatybilność wsteczna dla starszych przeglądarek, które nie obsługują interfejsu HTML state API. Wszystkie moje strony mają wspólną bazę kodu (pojedynczy minified & skompresowany plik js).

Oto zarys struktury, którą myślę o użyciu w mojej aplikacji: Tutaj wpisz opis obrazka

To zasadniczo podejście hybrydowe. Górna połowa składa się z rdzenia/fasady/modułu z dyskretnymi modułami, które nie wchodzą ze sobą bezpośrednio w interakcję i publikują / subskrybują powiadomienia za pośrednictwem fasady.

The dolna połowa składa się z mojej proponowanej struktury aplikacji, która powiadamia "główny kontroler", gdy zmieni się stan/url, główny kontroler wykonuje wszelkie globalne operacje (takie jak inicjalizacja menu nagłówka i paska bocznego mojego interfejsu użytkownika, jeśli nie jest już zainicjowany) i instruuje odpowiednią podkontrolę, aby uruchomiła metodę init () (jak również wywołanie destroy(); na dowolnym kontrolerze, który został wcześniej załadowany). Każdy podkontroler (koreluje z ex: Strona główna, Strona kalendarza, Strona rezerwacji itp.) cherry-wybiera moduły z puli dostępnych modułów i inicjalizuje je.

Czy to dobre podejście czy jestem na złym torze? Widzę, że moduły są nadal niezależne od siebie, co jest dobre dla skalowalności.

Rozważałem również traktowanie routera i kontrolerów jako dyskretnych modułów i zmuszenie ich do publikowania / subskrybowania rdzenia, a każdy kontroler w jakiś sposób inicjalizuje niezbędne moduły, których potrzebuje na swojej stronie.

Author: Casey Flynn, 2012-10-31

2 answers

Jedną z rzeczy, które zrobiliśmy, aby Historia działała płynnie, była pierwsza zmiana adresu URL. Po zmianie adresu URL zdarzenie zostanie wywołane, router przetworzy adres url, a następnie wykona co zrobić. To zdarzenie zostanie automatycznie wywołane również podczas ładowania strony. Jeśli klikniesz link, po prostu zmienisz adres URL, który jest dość prosty i całkowicie oddziela linki / przyciski od logiki aplikacji. To wydawało się działać dobrze dla naszej aplikacji. Użyliśmy JQM, ale zrzuciliśmy większość ich router ponieważ przeczytaliśmy większość naszych instrukcji z jakiegoś pliku XML i nie mieliśmy kilku stron HTML do załadowania do głównego obszaru widoku.

Często widziałem aplikacje szkieletowe używające routera jako rdzenia / mediatora. To dobry pomysł. Możesz po prostu słuchać zmian zdarzeń dla adresu URL, a następnie odpowiednio zmienić stronę. Ten Mediator powinien być prawdopodobnie singletonem, chociaż singletony są trudniejsze do testu jednostkowego.

Rzecz, z którą niekoniecznie się zgadzałem, to jej definicja "widoków". Widok wydaje się jakby akcją w kontrolerze (dobrze z niektórych perspektyw). W tym momencie dodaliśmy jeszcze jeden poziom separacji w naszej aplikacji. Nasze poglądy sprawiły, że żądania ajax do plików szablonów, które zostały wypełnione niektórymi JSONAMI i kierownicami.js. Powiedziałbym, że Twój nagłówek / pasek boczny powinien być tylko szablonami. Jeśli chcesz je odświeżyć, zobacz, jak możesz zrobić bardzo prosto, w przeciwnym razie patrzysz na utworzenie 4 nowych modułów: kolekcja dla listy, model dla każdego widok elementu, kolekcji i modelu. Chciałbym kilka szablonów bardziej ściśle z jakiegoś widoku wyższego poziomu, aż trzeba je dalej rozbić (np. niektóre "Application/Main View").

Posiadanie tej warstwy szablonu pozwala na wprowadzanie powierzchownych zmian bez rekompilacji, co jest miłe. Za każdym razem, gdy możesz umieścić rzeczy w "meta", jest to wygrana (no chyba, że wymaga to odczytu XML (ha)). Jako bonus Możesz również buforować szablon osobno (lub buforować go osobno Materia).

Twoja Architektura wydaje się jednak w porządku i jest poprawnym podejściem do twojego problemu. Jedna rada, którą bym dał, to nie przesadzaj z projektowaniem z góry. Iteracja jest najlepsza. Trzeba będzie refaktor. Nie można przewidzieć, co sprawi, że Twoja aplikacja będzie płynniejsza z 3-6-miesięcznym wyprzedzeniem.

Aktualizacja 18 grudnia 2013

Teraz używamy marionetki i więcej sztuczek addy osmani. Oprócz powyższych elementów używamy alternatywnego formatu AMD:

define(function(require) {
    var myTemplate = require('hb!mytemplate.handlebars'),
        view = require('myview');
    ...
});

We korzystają również z klasy aplikacji marionette w połączeniu z wreqr, który zapewnia warstwę żądania / odpowiedzi. Pozwala nam to na czyste ustawianie obiektów aplikacji. Pozwala nam również definiować klasy bez jawnego podawania nazwy klasy. To całkiem dobry sposób na piaskownicę. EG:

this.app.setHandler('CanvasClass', function() {
    return RaphaelCanvasView;
});

// elsewhere

this.app.request('CanvasClass').text('123', {x:1, y:2});
Wygląda na to, że wszystko dobrze się układa.

Należy również zamówić Aura js i web components. Nasza struktura katalogów naśladuje / antycypuje te pojęcia bez inwestowania jeszcze w nich.

 6
Author: Parris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-30 18:24:52

Myślę, że to dobre podejście. Rozwijałem coś podobnego w ogromnych komercyjnych aplikacjach internetowych 2 (minus kręgosłup i Niestandardowy menedżer historii) i działa świetnie. Nie używam również AMD i wszystkie interakcje są obsługiwane przez pub / sub. Jedną z moich najlepszych inspiracji (o których na pewno już wiecie) jest: https://github.com/aurajs/aura

 2
Author: tborychowski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-15 09:39:06