Dinamik modül setine sahip bir AngularJS uygulaması geliştirme


80

Kullanıcının (önceden tanımlanmış 100'den fazla widget'tan oluşan bir setten seçim yaparak) widget'ları koyabileceği (sürükle / bırak) ve her widget'in bir dizi veriyi (REST çağrısı kullanılarak getirilen) görüntüleyen özel bir uygulama olduğu karmaşık bir düzene sahip bir uygulamam var belirli bir şekilde. Tonlarca blog yazısı, stackoverflow sorusu ve resmi AngularJS dokümanları okudum, ancak uygulamamı bu gereksinimleri karşılayacak şekilde nasıl tasarlamam gerektiğini çözemiyorum. Demo uygulamalarına baktığımızda, tek bir modül (ng-app) var ve onu .js dosyasında oluştururken, bağımlı modüller bağımlılıkları olarak bildiriliyor, ancak büyük bir widget setim var ve bir şekilde hepsini tanımlamam tavsiye edilmez Orada. Aşağıdaki sorular için öneriye ihtiyacım var:

  • Uygulamamı ve widget'ları nasıl tasarlamalıyım - ayrı bir AngularJS modülüne mi sahip olmalıyım yoksa her widget ana modüle yönelik bir yönerge mi olmalı?
  • Widget'ımı yönergeler olarak tasarlarsam, bir yönerge içinde bağımlılığı tanımlamanın bir yolu var mı? Yani benim direktifimin uygulanmasında ng-takvim kullandığını söyleyebilir miyim?
  • Her widget'ı ayrı bir modül olarak tasarlarsam, widget modülünü dinamik olarak ana modüle bağımlılık olarak eklemenin bir yolu var mı?
  • Denetleyicileri nasıl tasarlamalıyım - parçacık başına muhtemelen bir denetleyici?
  • Görünümde aynı türden birden fazla widget'ım varsa durumu (kapsamı) nasıl ayırmalıyım?
  • AngularJS ile yeniden kullanılabilir pencere öğeleri tasarlamak için en iyi yöntemler var mı?

DÜZENLE

Yararlı referanslar:


1
İlk düşüncem, her bir parçacığı ng-include aracılığıyla oluşturulan bir çift ayrı HTML / JS dosyası olarak oluşturmak olurdu. İşin püf noktası, yalnızca gerekli denetleyici JS dosyalarını yüklemektir.
Shmiddty

Dinamik olarak ng-include içeren html ekleyebiliyorum?
Adrian Mitev

1
Öyle inanıyorum. Ana denetleyicinizde, hangi parçacığın etkin olduğunu tanımlayan bir koleksiyonunuz olur, koleksiyon için işaretlemede, söz konusu parçacığın HTML src görünümüne işaret eden bazı özelliğe ng-include bağlı olursunuz. Bunun işe yaradığından oldukça eminim, ama aslında böyle bir şey yapmadım.
Shmiddty

Yanıtlar:


60

Bunlar sadece genel tavsiyelerdir.

Uygulamamı ve widget'ları nasıl tasarlamalıyım - ayrı bir AngularJS modülüne mi sahip olmalıyım yoksa her widget ana modüle yönelik bir yönerge mi olmalı?

Yüzlerce widget'tan bahsediyorsunuz, onları birkaç modüle ayırmak doğal görünüyor. Bazı widget'ların diğer widget'lardan daha fazla ortak noktası olabilir. Bazıları çok genel olabilir ve diğer projelere uygun, diğerleri daha spesifik olabilir.

Widget'ımı yönergeler olarak tasarlarsam, bir yönerge içinde bağımlılığı tanımlamanın bir yolu var mı? Yani benim direktifimin uygulanmasında ng-takvim kullandığını söyleyebilir miyim?

Diğer modüllere bağımlılıkları bir modül düzeyinde yapılır, ancak modül eğer sorun yoktur Amodül bağlıdır Bve her iki Ave Bmodül bağlıdır C. Direktifler, Angular'da pencere öğesi oluşturmak için doğal bir seçimdir. Bir yönerge başka bir yönergeye bağlıysa, ya onları aynı modülde tanımlarsınız ya da bir modüler düzeyde bağımlılık yaratırsınız.

Her widget'ı ayrı bir modül olarak tasarlarsam, widget modülünü dinamik olarak ana modüle bağımlılık olarak eklemenin bir yolu var mı?

Bunu neden yapmak isteyeceğinden emin değilim ve nasıl yapacağımı da bilmiyorum. Direktifler ve hizmetler Angular'da kullanılmadan önce başlatılmaz. Çok büyük bir yönerge (gereçler) kitaplığınız varsa ve muhtemelen bazılarını kullanacağınızı, ancak hepsini kullanmayacağınızı biliyorsanız, ancak uygulama başlatıldığında hangilerinin kullanılacağını bilmiyorsanız, aslında "tembel modülünüz yüklendikten sonra direktiflerinizi yükleyin. Burada bir örnek oluşturdum

Bunun faydası, çok fazla kodunuz olsa bile uygulamanızın hızlı yüklenmesini sağlayabilmenizdir, çünkü komut dosyalarını ihtiyacınız olmadan önce yüklemeniz gerekmez. Dezavantajı, yeni bir direktif ilk yüklendiğinde önemli ölçüde gecikme olabilmesidir.

Denetleyicileri nasıl tasarlamalıyım - parçacık başına muhtemelen bir denetleyici?

Bir parçacığın muhtemelen kendi denetleyicisine ihtiyacı olacaktır. Denetleyiciler genellikle küçük olmalıdır, eğer büyürlerse bir hizmete daha iyi uyan herhangi bir işlev olup olmadığını düşünebilirsiniz.

Görünümde aynı türden birden fazla widget'ım varsa durumu (kapsamı) nasıl ayırmalıyım?

Kapsam değişkenlerine ihtiyaç duyan pencere öğelerinin şüphesiz kendi yalıtılmış kapsamları olmalıdır ( scope:{ ... }yönerge yapılandırmasında).

AngularJS ile yeniden kullanılabilir pencere öğeleri tasarlamak için en iyi yöntemler var mı?

Kapsamı izole edin, bağımlılıkları gerekli minimumda tutun. Angular'daki en iyi uygulamalarla ilgili Misko'nun videosunu izleyin

Brian Ford ayrıca Angular'da devasa bir uygulama yazma hakkında bir makale yazdı.


Harika cevap için teşekkürler!
Adrian Mitev

17

Bu soru benim için de çok önemli. AngularJS ana sayfasında birkaç örnek var (bunlara widget diyebilirsiniz), bu yüzden widget'larını nasıl ayırdıklarını görmek için kaynak kodlarının üzerinden geçtim.

İlk olarak, asla bir "ng-app" özniteliği bildirmezler. Onlar kullanırlar

function bootstrap() {
      if (window.prettyPrint && window.$ && $.fn.popover && angular.bootstrap &&
          hasModule('ngLocal.sk') && hasModule('ngLocal.us') && hasModule('homepage') && hasModule('ngResource')) {
            $(function(){
              angular.bootstrap(document, ['homepage', 'ngLocal.us']);
            });
      }
    }

her şeyin doğru yüklendiğinden emin olmak için. Güzel fikir, ancak ng-app özelliğini size çok fazla itmeleri ve sonra kendileri bile kullanmamaları tuhaf. Her neyse, burada uygulamayla yükledikleri ana sayfa modülü - http://angularjs.org/js/homepage.js

AppRun adında bir yönerge var

  .directive('appRun', function(fetchCode, $templateCache, $browser) {
    return {
      terminal: true,
      link: function(scope, element, attrs) {
        var modules = [];

        modules.push(function($provide, $locationProvider) {
          $provide.value('$templateCache', {
            get: function(key) {
              var value = $templateCache.get(key);
              if (value) {
                value = value.replace(/\#\//mg, '/');
              }
              return value;
            }
          });
          $provide.value('$anchorScroll', angular.noop);
          $provide.value('$browser', $browser);
          $locationProvider.html5Mode(true);
          $locationProvider.hashPrefix('!');
        });
        if (attrs.module) {
          modules.push(attrs.module);
        }

        element.html(fetchCode(attrs.appRun));
        element.bind('click', function(event) {
          if (event.target.attributes.getNamedItem('ng-click')) {
            event.preventDefault();
          }
        });
        angular.bootstrap(element, modules);
      }
    };
  })

Yapılacaklar listesini örnek olarak kullanacağım. Html için,

<div app-run="todo.html" class="well"></div>

ve sonra sayfanın alt kısmında

<script type="text/ng-template" id="todo.html">
  <h2>Todo</h2>
  <div ng-controller="TodoCtrl">
    <span>{{remaining()}} of {{todos.length}} remaining</span>
    [ <a href="" ng-click="archive()">archive</a> ]
    <ul class="unstyled">
      <li ng-repeat="todo in todos">
        <input type="checkbox" ng-model="todo.done">
        <span class="done-{{todo.done}}">{{todo.text}}</span>
      </li>
    </ul>
    <form ng-submit="addTodo()">
      <input type="text" ng-model="todoText"  size="30"
             placeholder="add new todo here">
      <input class="btn-primary" type="submit" value="add">
    </form>
  </div>
</script>

Onlar ayrıca sahip

<style type="text/css" id="todo.css"> //style stuff here </style>
<script id="todo.js"> //controller stuff here </script>

Kod kullanılır, ancak bu komut dosyalarındaki id öznitelikleri uygulamayı çalıştırmak için önemli değildir. Bu sadece uygulamanın solundaki kaynak kodu görüntüsü içindir.

Temel olarak, fetchCode işlevini kullanan appRun adlı bir yönergeye sahiptirler.

  .factory('fetchCode', function(indent) {
    return function get(id, spaces) {
      return indent(angular.element(document.getElementById(id)).html(), spaces);
    }
  })

kodu almak için. Daha sonra yeni bir uygulama oluşturmak için angular.bootstrap () kullanırlar. Ayrıca uygulama tarafından çalıştırılarak modülleri yükleyebilirler. JavaScript Projesi örneği şu şekilde başlatılır:

<div app-run="project.html" module="project" class="well"></div>

Umarım bu yardımcı olur. Hala "en iyi" tekniğin ne olduğundan emin değilim, ancak AngularJS ana sayfası her örnek / widget için tamamen ayrı bir açısal uygulama (ng-app) kullanıyormuş gibi görünüyor. AJAX ile bir şeyler elde etmek için fetchCode işlevini değiştirmek dışında aynısını yapacağımı düşünüyorum.


3
Bunun için +1. Burada benzer bir sorum var sanırım size yardımcı olabileceğinizi düşünüyorum: stackoverflow.com/questions/17557088/…
Dan Kanze

beni doğru yönü gösterdin. HasModule işleviyle ilgilenenler için uygulamamı burada bırakacağım:function hasModule(name) { try { angular.module(name); } catch(err) { return false; } return true; }
Asier Paz
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.