2017-02-27 63 views
15

Od pewnego czasu śledzę numer Modular Design Pattern i uważam, że jest on niezwykle użyteczny, ponieważ pomaga w utrzymaniu kodu & rozdzielanie bloków na moduły.Używanie modularnego wzorca projektowego w JavaScript z ustawieniami DOM

Regularne korzystanie z konstrukcji modułowej z jQuery doprowadziła do większości moich aplikacji/kod zgodnie z poniższą strukturą:

(function() { 
    var chat = { 
     websocket: new WebSocket("ws://echo.websocket.org/"), 
     that: this, 
     init: function() { 
      this.scrollToBottom(); 
      this.bindEvents(); 
      this.webSocketHandlers(); 
     }, 
     bindEvents: function() { 
      this.toggleChat(); 
      this.filterPeople(); 
      this.compose(); 
     }, 
     elements: { 
      indicator: $(".indicator"), 
      statusText: $(".status-text"), 
      chatHeadNames: $(".people li .name"), 
      filterInput: $("#filter-input"), 
      msgInput: $("#msg-input"), 
      sendBtn: $(".send") 
     }, 
     ... 
     ... 
     ... 
     filterPeople: function() { 
      var that = this; 
      this.elements.chatHeadNames.each(function() { 
       $(this).attr('data-search-term', $(this).text().toLowerCase()); 
      }); 
     }, 
     ... 
     ... 
     }; 

     chat.init(); 
})(); 

Co chciałbym wiedzieć, czy przedstawieniu wszystkie moje elementy poprzez jQuery jako część pojedyncza zmienna to dobra praktyka ?

Jedna część mnie mówi, że rzeczywiście jest dobrym sposobem na odnoszenie się do wszystkich selektorów naraz i buforowanie ich w zmiennych, tak aby wielokrotne użycie tego samego elementu można było wykonać z buforowanymi zmiennymi (zamiast wielu wybranych DOM).

Inna część mnie mówi, że to może być anty-wzór, a poszczególne elementy powinny być wybrane i buforowane lokalnie, gdy jest to wymagane.

Użyłem podobnych struktur i mam mieszane odpowiedzi na temat kodu, ale nic solidnego. Każda pomoc będzie doceniona. Dzięki!

+0

użycie elementu do wyboru nazwy i statusu lub innych rzeczy nie jest dobrym pomysłem co się stanie, jeśli ktoś zmieni nazwę z elementem inspekcji? lub jutro twój kolega z drużyny, zmieniając temat, wszystko będzie zepsute! –

+0

Przechowuj dane w pamięci lub obiekcie i do przechowywania użyj localstorage –

+0

Właściwości elementu są analizowane podczas ładowania strony, a zdarzenia są powiązane bezpośrednio z węzłem, więc jeśli ktoś zmieni nazwę za pomocą elementu inspect, nie spowoduje to problemu. A "localstorage" to zły pomysł. – nashcheez

Odpowiedz

9

Buforowanie selektorów to dobra rzecz. Trzymanie się ich jest dobrym pomysłem. Poprawia wydajność poprzez wielokrotne wysyłanie zapytań do DOM dla tego samego. Powyższy kod wygląda bardzo podobnie do kodu BackboneJS i MarionetteJS.

mam pewne ostrzeżenia dla ciebie choć:

  1. Ten wzór może spowodować wycieki pamięci. Rozważ przypadek, w którym zniszczysz wywiady, ale zachowujesz odniesienie do czegoś, co je wybrało. Nazywa się to zwisającym wskaźnikiem. Widok naprawdę nie zniknie. Wszystkie powiązania pozostaną. Wydarzenia będą nadal strzelać za kulisami.
  2. W końcu wpadniesz na błąd, w którym zdecydowałeś się ponownie renderować część ekranu. Czyszczenie wszystkich wiązań jest wtedy wymagane i musisz pamiętać, aby usunąć i selektory. Jeśli tego nie zrobisz, prawie na pewno napotkasz problemy, w których zastanawiasz się, dlaczego wydarzenie rzeczywiście się odbywa, ale na ekranie nic się nie dzieje ... (dzieje się tak dlatego, że dzieje się to poza ekranem, do elementu, który wypróbowałeś usunąć, to wciąż istnieje ... sorta).
  3. Obecny sposób wyszukiwania elementów powoduje wyszukiwanie na całej stronie. Spójrz na https://api.jquery.com/find/. Jeśli buforujesz jeden selektor, a następnie przeprowadzasz wyszukiwania w obrębie tego selektora, może to spowodować niewielki wzrost wydajności.
+0

1. Co zrobić, jeśli nie używam szkieletu, takiego jak szkielet, co zwykle ma miejsce, wtedy żadne subviews nie są niszczone i nie ma scenariuszy zwisającego wskaźnika. 2. Zdarzenia, o ile nie są delegowane, są powiązane bezpośrednio z węzłem DOM, więc w przypadku, gdy usunę węzeł elementu, zdarzenie powiązane zostanie automatycznie odłączone. 3. Używam 'jQuery.find' na moich buforowanych selektorach do przeszukiwania elementów potomnych. – nashcheez

+0

@nashcheez nie trzeba używać ramy, wystarczy zbudować własny system, który zajmie się czyszczeniem (jeśli to konieczne). Istnieje wiele aplikacji, które nie muszą obsługiwać żadnego rodzaju czyszczenia. W każdym razie, nic z tego nie ma znaczenia, to nadal jest dobry wzór. Jeśli potrzebujesz oczyszczenia, łatwiej znajdziesz to, co chcesz wyczyścić. – Parris

+0

Oczywiście dzięki za odpowiedź. Zrobię trochę moich badań na ten sam temat. :) – nashcheez

0

Zgadzam się z Parris, jakie selektory buforowania jest dobra. W naszym projekcie używamy DI i wzoru Facade. Ta struktura ma konfigurację json na wypadek, gdyby nowy moduł był inną strukturą.

Chyba najbardziej:

  • ustawienia wyślij konfiguracyjnym
  • cache elems only elems key;
  • nie buforować elementów dinamics w params.classes;
  • odkładają wspólną funkcję w helperach; Na przykład:

    (function() { 
    var chat = { 
        websocket: new WebSocket("ws://echo.websocket.org/"), 
        that: this, 
        params: { 
         elems: { 
          module: '.container', 
          indicator: ".indicator", 
          statusText: ".status-text", 
          chatHeadNames: ".people li .name", 
          filterInput: "#filter-input", 
          msgInput: "#msg-input", 
          sendBtn: ".send" 
         } 
         classes: { 
          dinamicInput: '.dinamicInput' 
         } 
        }, 
        init: function(params) { 
         opts = $.extend(true, $.extend(true, {}, that.params), params); 
         that.initElementsForModule(that.elements, that.params.elems); 
         this.scrollToBottom(); 
         this.bindEvents(); 
         this.webSocketHandlers(); 
        }, 
        bindEvents: function() { 
         this.toggleChat(); 
         this.filterPeople(); 
         this.compose(); 
        }, 
    
        initElementsForModule = function (elements, identifiers) { 
         var $module, 
          prop; 
    
         for (prop in identifiers) { 
          if (identifiers.hasOwnProperty(prop) && prop !== "module") { 
           elements["$" + prop] = $module.find(identifiers[prop]); 
          } 
         } 
    
        }, 
    
        elements: { 
         module: null, 
         indicator: null, 
         statusText: null, 
         chatHeadNames: null, 
         filterInput: null, 
         msgInput:null, 
         sendBtn: null 
        }, 
        ... 
        ... 
        ... 
        filterPeople: function() { 
         var that = this; 
         this.elements.chatHeadNames.each(function() { 
          $(this).attr('data-search-term', $(this).text().toLowerCase()); 
         }); 
        }, 
        ... 
        ... 
        }; 
    
        chat.init(); 
    })(); 
    
1
  • myślę, Jeśli moduł czatu ma selektorów tylko dla swoich dzieci, to jest to dobry wzór. Jak:
<div id="chat-module"> 
    <div class="indicator">...</div> 
    <div class="status-text">...<div> 
    ... 
</div> 
<script src="and your chat module.js"></script> 
// your chat module selecting .indicator: 
// $('#chat-module.indicator') 
  • Również dodać funkcję odcinający do modułu. Tak więc, po usunięciu go z widoku (, jak w jednostronicowej aplikacji), można unieważnić selektory i odłączyć procedury obsługi zdarzeń, takie jak: delete this.elements.indicator i kod odłączający zdarzenie.

Istnieją także inne/lepsze wzory na to, jak, kiedy użytkownik wpisze coś, ogień zdarzenie i złapać tego zdarzenia w module. Aby oddzielić interfejs użytkownika i kod.

Powiązane problemy