SORU
19 ŞUBAT 2013, Salı


Angular.js bittiğinde gönderme olayı yükleniyor

ne sayfa yükleme bitirmek tüm direktifleri derleme bittiğinde/önyükleme, algılamak için en iyi yolu nedir merak bağlama/

herhangi bir olay zaten orada? bootstrap fonksiyonu aşırı yük gerekir?

herhangi bir fikir için teşekkürler Lior

CEVAP
18 Mayıs 2014, Pazar


Sadece bir önsezi: neden ngCloak Direktif geliyor bak nasıl? Açıkça ngCloak yönergesi şeyler yüklemiş sonra içeriği göstermek için yönetir. NgCloak bakarak kesin cevap yol açacaktır eminim...

1 saat sonra EDİT: Tamam, ngCloak baktım ve gerçekten çok kısa. Bu açıkça anlaşılacağı gibi, derleme işlevi kadar idam almazsınız {{şablon}} ifadeler (dolu şablon gibi) değerlendirilmiştir, bu nedenle ngCloak Direktifi güzel işlevselliği.

Benim tahminime göre sadece ngCloak aynı sadeliği ile bir Direktif yapmak için, daha sonra işlevi ne yapmak istersen yap derlemek olacaktır. :) Uygulamanızın kök öğesi. Direktif yer Direktif myOnload gibi bir şey diyebilirsin ve nitelik olarak benim-yüklendiğinde kullanın. Derleme işlev şablon derlenmiş bir kez çalıştırmak (ifadeler değerlendirilmiş ve alt şablonları yüklü).

23 saat sonra EDİT: Tamam, bu yüzden biraz araştırma yaptım, ve ben de 50**. Bu soru, ama dolaylı olarak ilgili sorduğum soruyu tesadüfen bu soruyu çözen cevap için bana yol açar.

Cevap oluşturabilirsiniz basit Yönerge ve koyun kodunuzu Yönerge bağlantı işlevi, (en kullanım durumları, aşağıda açıklanan) çalıştırıldığında eleman hazır/dolu. Josh's description of the order in which compile and link functions are executed dayalı

bu işaretleme varsa:

<div directive1>
  <div directive2>
    <!-- ... -->
  </div>
</div>

Sonra AngularJS Direktifi çalıştırarak yönergeleri oluşturur belli bir düzen içinde fonksiyonlar:

directive1: compile
  directive2: compile
directive1: controller
directive1: pre-link
  directive2: controller
  directive2: pre-link
  directive2: post-link
directive1: post-link

Düz bir işlevi "açık" post-link, dış link yani varsayılan olarak directive1 bağlantı işlevi iç sonrasına kadar çalışmayacak directive2 bağlantı koştu işlevi vardır. Sadece bu yüzden diyoruz ki ... güvenli post-bağlantı DOM manipülasyon yapmak. Orijinal doğru yani soru, sorun, alt direktifin erişim olmalı hayır dış direktifin bağlantısından iç html gerçi fonksiyonu dinamik olarak içeriğini yukarıda söylediğim gibi derlenmiş olmalıdır eklenmiş.

Bu her şeyi/derlenen/dolu/bağlantı hazır olduğunda sadece bir Direktifi bizim kod çalıştırmak için yapabileceğimiz sonucuna varabiliriz:

    app.directive('ngElementReady', [function() {
        return {
            priority: -1000, // a low number so this directive loads after all other directives have loaded. 
            restrict: "A", // attribute only
            link: function($scope, $element, $attributes) {
                console.log(" -- Element ready!");
                // do what you want here.
            }
        };
    }]);

Şimdi ne yapacaksınız bir app kök öğesi üzerine ngElementReady Direktifi ve console.log yüklü olduğunda ateş

<body data-ng-app="MyApp" data-ng-element-ready="">
   ...
   ...
</body>

Bu kadar basit! Sadece basit bir yönerge olun ve bunu kullanın. ;)

Daha fazla $scope.$eval($attributes.ngElementReady); ekleyerek bir ifade (fonksiyon gibi) çalıştırmak böylece özelleştirebilirsiniz:

    app.directive('ngElementReady', [function() {
        return {
            priority: Number.MIN_SAFE_INTEGER, // execute last, after all other directives if any.
            restrict: "A",
            link: function($scope, $element, $attributes) {
                $scope.$eval($attributes.ngElementReady); // execute the expression in the attribute.
            }
        };
    }]);

Sonra herhangi bir öğe üzerinde kullanabilirsiniz:

<body data-ng-app="MyApp" data-ng-controller="BodyCtrl" data-ng-element-ready="bodyIsReady()">
    ...
    <div data-ng-element-ready="divIsReady()">...<div>
</body>

Senin elemanın altında yaşayan sadece fonksiyonlarını (örneğin bodyİsReady ve divİsReady) kapsamında tanımlanan emin (denetleyicisi).

Uyarılar: bu iş olacak dedimendurumda. NgRepeat ve ngİf gibi bazı direktifleri kullanırken dikkatli olun. Kendi kapsam oluşturmak, ve sizin göreviniz ateş olmayabilir. Ayrıca ngİf bir öğe üzerinde yeni ngElementReady kuralı koymak ve ngİf durumu false ise ngElementReady amacımız sarhoş olmaz. Ya da, örneğin, ayrıca ngİnclude bir yönerge bir öğe üzerinde yeni ngElementReady kuralı koyarsanız, bizim Direktifi eğer ngİnclude için şablon varsa yüklü olmayacak. Aynı eleman üzerine koyarak yerine direktifleri yuva sağlayarak bu sorunları üstesinden gelebilirsiniz. Bunu yaparak örneğin:

<div data-ng-element-ready="divIsReady()">
    <div data-ng-include="non-existent-template.html"></div>
<div>

bunun yerine:

<div data-ng-element-ready="divIsReady()" data-ng-include="non-existent-template.html"></div>

NgElementReady yönergesi ikinci örnekte derleneceği, ama bağlantı fonksiyonu çalıştırılmaz. Not: yönergeleri her zaman derlenmiş, ama bağlantı fonksiyonları her zaman yukarıdaki gibi bazı senaryolar bağlı olarak yürütülür.

DÜZEN, bir kaç dakika sonra:

Oh, ve tam olarak bu soruyu cevaplamak için, şimdi 25 ** 26 ** ng-element-ready öznitelik yürütülen bir ifade veya işlev olay. :) Örn.:

<div data-ng-element-ready="$emit('someEvent')">
    ...
<div>

Daha birkaç dakika sonra DÜZENLEYİN:

@satchmorun cevap çok, ama sadece ilk yükleme için çalışıyor. İşte sipariş şeyler bağlantı özellikleri, app.run, ve diğerleri de dahil olmak üzere yürütülen açıklayan very useful SO question. Yani kullanmanız durumunda, app.run bağlı olarak iyi, ama bu durumda bağlantı fonksiyonları daha iyi belirli unsurları için değil olabilir.

DÜZENLEME, beş ay sonra, 8:11 PST Ekim 17:

Bu zaman uyumsuz olarak yüklenen şiddetli çalışmıyor. İhtiyacınız olacak eklemek defter tutma halinde kalıntılar (örneğin, tek yönlü olduğu için her kısmi takip edin zaman içeriği yapılır yükleniyor sonra yayan bir olay yani üst kapsam sayarım kaç tane numune var yüklü ve son olarak ne ihtiyaç duyduğu için sonra tüm parçaları yüklendi).

DÜZENLEMEK, 10:52pm PST de 23 Ekim

Bir resim yüklendiğinde ateş için basit bir yönetmelik kodu yaptım:

/*
 * This img directive makes it so that if you put a loaded="" attribute on any
 * img element in your app, the expression of that attribute will be evaluated
 * after the images has finished loading. Use this to, for example, remove
 * loading animations after images have finished loading.
 */
  app.directive('img', function() {
    return {
      restrict: 'E',
      link: function($scope, $element, $attributes) {
        $element.bind('load', function() {
          if ($attributes.loaded) {
            $scope.$eval($attributes.loaded);
          }
        });
      }
    };
  });

DÜZENLEME, 12:48am PST Ekim 24:

ngElementReady orijinal talimatımı geliştirdim ve whenReady yeniden adlandırıldı.

/*
 * The whenReady directive allows you to execute the content of a when-ready
 * attribute after the element is ready (i.e. done loading all sub directives and DOM
 * content except for things that load asynchronously like partials and images).
 *
 * Execute multiple expressions by delimiting them with a semi-colon. If there
 * is more than one expression, and the last expression evaluates to true, then
 * all expressions prior will be evaluated after all text nodes in the element
 * have been interpolated (i.e. {{placeholders}} replaced with actual values). 
 *
 * Caveats: if other directives exists on the same element as this directive
 * and destroy the element thus preventing other directives from loading, using
 * this directive won't work. The optimal way to use this is to put this
 * directive on an outer element.
 */
app.directive('whenReady', ['$interpolate', function($interpolate) {
  return {
    restrict: 'A',
    priority: Number.MIN_SAFE_INTEGER, // execute last, after all other directives if any.
    link: function($scope, $element, $attributes) {
      var expressions = $attributes.whenReady.split(';');
      var waitForInterpolation = false;

      function evalExpressions(expressions) {
        expressions.forEach(function(expression) {
          $scope.$eval(expression);
        });
      }

      if ($attributes.whenReady.trim().length == 0) { return; }

      if (expressions.length > 1) {
        if ($scope.$eval(expressions.pop())) {
          waitForInterpolation = true;
        }
      }

      if (waitForInterpolation) {
        requestAnimationFrame(function checkIfInterpolated() {
          if ($element.text().indexOf($interpolate.startSymbol()) >= 0) { // if the text still has {{placeholders}}
            requestAnimationFrame(checkIfInterpolated);
          }
          else {
            evalExpressions(expressions);
          }
        });
      }
      else {
        evalExpressions(expressions);
      }
    }
  }
}]);

Örneğin, bu gibi bir öğesi yüklenir ve {{placeholders}} henüz yerine someFunction ateş kullanın:

<div when-ready="someFunction()">
  <span ng-repeat="item in items">{{item.property}}</span>
</div>

someFunction item.property tüm yer tutucular değiştirilir önce çağrılır.

İstediğiniz kadar ifadeleri değerlendirmek ve son ifadenin true {{placeholders}} bu gibi değerlendirilecek beklemek olun:

<div when-ready="someFunction(); anotherFunction(); true">
  <span ng-repeat="item in items">{{item.property}}</span>
</div>

someFunction anotherFunction {{placeholders}} yerini, sonra işten atılacak.

Bu sadece bir unsuru, gelecekteki değişiklikleri yüklemek ilk kez çalışır. Eğer $digest bir tutar yer tutucular sonra olmaya başlangıçta almıştır eğer ($a Özet 10 kata kadar veri değiştirme durana kadar olabilir) istediğiniz gibi çalışmayabilir. Kullanımı vakaların büyük bir çoğunluğu için uygun olacak.

DÜZENLEMEK, 7:26pm PST Ekim 31:

Tamam, belki de bu son yaşadığım son güncelleme. Bu muhtemelen kullanım durumları 99.999 için çalışır:

/*
 * The whenReady directive allows you to execute the content of a when-ready
 * attribute after the element is ready (i.e. when it's done loading all sub directives and DOM
 * content). See: http://stackoverflow.com/questions/14968690/sending-event-when-angular-js-finished-loading
 *
 * Execute multiple expressions in the when-ready attribute by delimiting them
 * with a semi-colon. when-ready="doThis(); doThat()"
 *
 * Optional: If the value of a wait-for-interpolation attribute on the
 * element evaluates to true, then the expressions in when-ready will be
 * evaluated after all text nodes in the element have been interpolated (i.e.
 * {{placeholders}} have been replaced with actual values).
 *
 * Optional: Use a ready-check attribute to write an expression that
 * specifies what condition is true at any given moment in time when the
 * element is ready. The expression will be evaluated repeatedly until the
 * condition is finally true. The expression is executed with
 * requestAnimationFrame so that it fires at a moment when it is least likely
 * to block rendering of the page.
 *
 * If wait-for-interpolation and ready-check are both supplied, then the
 * when-ready expressions will fire after interpolation is done *and* after
 * the ready-check condition evaluates to true.
 *
 * Caveats: if other directives exists on the same element as this directive
 * and destroy the element thus preventing other directives from loading, using
 * this directive won't work. The optimal way to use this is to put this
 * directive on an outer element.
 */
app.directive('whenReady', ['$interpolate', function($interpolate) {
  return {
    restrict: 'A',
    priority: Number.MIN_SAFE_INTEGER, // execute last, after all other directives if any.
    link: function($scope, $element, $attributes) {
      var expressions = $attributes.whenReady.split(';');
      var waitForInterpolation = false;
      var hasReadyCheckExpression = false;

      function evalExpressions(expressions) {
        expressions.forEach(function(expression) {
          $scope.$eval(expression);
        });
      }

      if ($attributes.whenReady.trim().length === 0) { return; }

    if ($attributes.waitForInterpolation && $scope.$eval($attributes.waitForInterpolation)) {
        waitForInterpolation = true;
    }

      if ($attributes.readyCheck) {
        hasReadyCheckExpression = true;
      }

      if (waitForInterpolation || hasReadyCheckExpression) {
        requestAnimationFrame(function checkIfReady() {
          var isInterpolated = false;
          var isReadyCheckTrue = false;

          if (waitForInterpolation && $element.text().indexOf($interpolate.startSymbol()) >= 0) { // if the text still has {{placeholders}}
            isInterpolated = false;
          }
          else {
            isInterpolated = true;
          }

          if (hasReadyCheckExpression && !$scope.$eval($attributes.readyCheck)) { // if the ready check expression returns false
            isReadyCheckTrue = false;
          }
          else {
            isReadyCheckTrue = true;
          }

          if (isInterpolated && isReadyCheckTrue) { evalExpressions(expressions); }
          else { requestAnimationFrame(checkIfReady); }

        });
      }
      else {
        evalExpressions(expressions);
      }
    }
  };
}]);

Bu gibi kullanın

<div when-ready="isReady()" ready-check="checkIfReady()" wait-for-interpolation="true">
   isReady will fire when this {{placeholder}} has been evaluated
   and when checkIfReady finally returns true. checkIfReady might
   contain code like `$('.some-element').length`.
</div>

Tabii ki, muhtemelen optimize edilmiş olabilir, ama sadece bu bırakacağım. requestAnimationFrame hoş.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • dcigs

    dcigs

    9 EYLÜL 2006
  • graham025

    graham025

    25 NİSAN 2006