SORU
11 Mayıs 2013, CUMARTESİ


Ng-tekrar ediyorum, içine bir yönerge kullanarak ve kapsam gizemli bir güç '@'

Eğer çalışan bir kod soru görmek isterseniz, buradan başlayın: http://jsbin.com/ayigub/2/edit

Bu basit bir direcive yazmak için neredeyse eşdeğer yollarını düşünün:

app.directive("drinkLonghand", function() {
  return {
    scope: {},
    template: '<div>{{flavor}}</div>',
    link: function(scope, element, attrs) {
      scope.flavor = attrs.flavor;
    }
  };
});

app.directive("drinkShortcut", function() {
  return {
    scope: { flavor: '@'},
    template: '<div>{{flavor}}</div>'
  };
});

Kendileri tarafından kullanıldığında, iki direktifler çalışma ve aynı şekilde davranır:

  <!-- This works -->
  <div drink-longhand flavor="strawberry"></div>
  <hr/>

  <!-- This works -->
  <div drink-shortcut flavor="blueberry"></div>
  <hr/>

Ng-repeat içinde kullanıldığında ancak, sadece kısayol sürümü çalışır:

  <!-- Using the shortcut inside a repeat also works -->
  <div ng-repeat="flav in ['cherry', 'grape']">
    <div drink-shortcut flavor="{{flav}}"></div>
  </div>
  <hr/>

  <!-- HOWEVER: using the longhand inside a repeat DOESN'T WORK -->      
  <div ng-repeat="flav in ['cherry', 'grape']">
    <div drink-longhand flavor="{{flav}}"></div>
  </div>

Benim sorular şunlardır:

  1. Neden uzun versiyonu ng-repeat içinde çalışmıyor?
  2. Ne kadar uzun versiyonu içinde ng-tekrar bir çalışma yapabilir misin?

CEVAP
11 Mayıs 2013, CUMARTESİ


drinkLonghand kod kullanın

scope.flavor = attrs.flavor;

Bağlantı aşamasında, aralıklı öznitelikleri henüz değerlendirilmiş değil, kendi değerleri undefined. (Bu gibi durumlarda dize aradeğerleme kullanılarak değil, sadece normal, sıradan bir dize geçirmeden olduğun için ng-repeat dışında çalışıyorlar, örneğin "çilek".) Bu Directives developer guide, bulunmayan Attributes bir yöntem ile birlikte in the API documentation $observe adı: söz edilir

$observe ilişkilendirme (src="{{bar}}" vs.) içeren öznitelik değeri değişiklikleri gözlemlemek için kullanın. Sadece bu çok verimli ama aynı zamanda tek yolu kolayca elde gerçek değerini çünkü bağlama evre sırasında bu filmlerde olmadı henüz değerlendirdi ve değeri de bu saati ayarlamak için undefined.

Bu yüzden, düzeltmek içinbusorun, drinkLonghand Direktif bu gibi görünmelidir:

app.directive("drinkLonghand", function() {
  return {
    template: '<div>{{flavor}}</div>',
    link: function(scope, element, attrs) {
      attrs.$observe('flavor', function(flavor) {
        scope.flavor = flavor;
      });
    }
  };
});

Ancak, bu sorun değil bir kapsam izole; bu nedenle, satır

scope.flavor = flavor;

kapsam flavor adında önceden varolan bir değişkeni üzerine potansiyeline sahiptir. Boş bir kapsam ekleme de çalışmıyor izole; bu Açısal dize sokmak için çalışır, çünkü hangi üzerine özniteliği flav adı yok bu direktifin kapsamı, temel. (scope.flav = 'test'; çağrı yukarıda*.* 29) ekleyerek test edebilirsiniz

Elbette, kapsam izole tanımlama ile bunu halledebiliriz

scope: { flav: '@flavor' }

ya da bir oluşturarak olmayan izole alt kapsamı

scope: true

ya {{flavor}} 32 *güvenmek yerine, doğrudan DOM tarafından manipülasyon gibi

attrs.$observe('flavor', function(flavor) {
  element.text(flavor);
});

ama bu egzersizin amacı daha kolay sadece drinkShortcut yöntemi kullanmak olur (örn yendi. Yani, bu yönerge çalışmaları yapmak, $parent Direktif üzerinde aradeğerleme kendimiz yapmak $interpolate service kapsam ayrılırız:

app.directive("drinkLonghand", function($interpolate) {
  return {
    scope: {},
    template: '<div>{{flavor}}</div>',
    link: function(scope, element, attrs) {
      // element.attr('flavor') == '{{flav}}'
      // `flav` is defined on `scope.$parent` from the ng-repeat
      var fn = $interpolate(element.attr('flavor'));
      scope.flavor = fn(scope.$parent);
    }
  };
});

Tabii ki, bu sadece işleri için başlangıç değeri scope.$parent.flav; eğer değeri değiştirmek mümkün ... bilemiyorum use $watch ve yeniden değerlendirme sonucu sokmak fonksiyonu fn (değilim olumlu üstünü kafamda nasıl olur biliyor $watch; sen sadece, pas içinde bir fonksiyon). scope: { flavor: '@' } tüm bu karmaşıklığı yönetmek zorunda kalmamak için güzel bir kısayol.

[Güncelleme]

Yorum soru cevap için:

Nasıl kısayol yöntemi perde arkasında bu sorunu çözüyor mu? Senin gibi $sokmak hizmeti kullanıyor, yoksa başka bir şey yapıyor?

Kaynak baktım bu konuda emin değildim. compile.js aşağıdakileri buldum:

forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {
   var match = definiton.match(LOCAL_REGEXP) || [],
       attrName = match[2]|| scopeName,
       mode = match[1], // @, =, or &
       lastValue,
       parentGet, parentSet;

   switch (mode) {

     case '@': {
       attrs.$observe(attrName, function(value) {
         scope[scopeName] = value;
       });
       attrs.$$observers[attrName].$$scope = parentScope;
       break;
     }

attrs.$observe dahili öznitelik gözlem (break yukarıdaki son satırı, bir sonraki) Bankası için geçerli olandan farklı bir kapsam için bitmiş gibi görünüyor. Süre olabilir cazip kullanın Bu kendinizi, unutmayın, hiçbir şey ile çift dolar $$ önek düşünülmelidir özel Açısal özel API ve konu değişikliği olmadan uyarı (söz değil bu bedava zaten kullanırken @ modu).

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

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • 2ndfloor91

    2ndfloor91

    17 Kasım 2007
  • Android Central

    Android Cent

    13 Kasım 2008
  • Trevor Eckhart

    Trevor Eckha

    19 Aralık 2009