2015-04-24 10 views
10

:Uygun yolu bağlantısında yürütülmesi için direktifine fonksiyonları geçmesine Ben genellikle izole bir kapsam aracılığıyla direktiflerine fonksiyonları geçmesine biliyorum

.directive('myComponent', function() { 
    return { 
     scope:{ 
      foo: '&' 
     }   
    }; 
}) 

Ve sonra şablonda böyle gibi bu işlevini çağırabilirsiniz:

myVal kapsamı alır ebeveynde foo işlev parametrenin adı
<button class="btn" ng-click="foo({ myVal: value })">Submit</button> 

. scope.foo orijinal fonksiyonun sarıcı görevi gören bu yana scope.foo()(value): yerine şablonun link işlevinden bu kullanmayı düşünüyorsanız

Şimdi, onu aramak zorunda kalacaktır. Bu bana biraz sıkıcı geliyor. Ben = kullanarak myComponent yönergesi fonksiyonu geçerseniz

:

.directive('myComponent', function() { 
    return { 
     scope:{ 
      foo: '=' 
     }   
    }; 
}) 

Sonra sadece benim bağlantı işlevinden scope.foo(value) kullanmak mümkün olacak. Bu, işlevler üzerinde 2 yönlü bağlamayı kullanmak için geçerli bir kullanım durum mu, yoksa yapmamam gereken bir çeşit hack yapıyorum?

+0

Bu konuyla ilgili yanlış bir şey göremiyorum, ancak bir servise başvurmayı düşünebilirsiniz. – Mosho

+0

Kararsızım, çünkü veri modeli için 2 yönlü bağlanma tasarlanmış gibi görünüyor, ancak bunu bir işlevde kullanıyorum. Genel olarak, bu işlevlerin yine de değiştirilmesi beklenmemektedir. –

cevap

19

vb bazı "olay" işlevleri gibi when-drop, on-leave, ng-click, when-it-is-loaded ile kullanılmaktadır.

İlk olarak, direktiflerine işlev başvuruları geçmek '=' kullanmak asla.

'=' iki saat oluşturur ve bunları hem yönerge kapsamı hem de ana kapsam referanslarının aynı olduğundan emin olmak için kullanır (iki yönlü ciltleme). Bir yönergesinin ana kapsamınızdaki bir işlev tanımını değiştirmesine izin vermek gerçekten kötü bir fikirdir; bu, bu tür bir bağlama kullandığınızda gerçekleşen şeydir. Ayrıca, saatler en aza indirilmelidir - işe yarayacak, iki ekstra $ saatler gereksizdir. Öyleyse bu iyi değil - oylamanın bir kısmı, bunu önerdi.

İkincisi - cevap, '&' ifadesinin ne yaptığını yanlış bildirir. &, "tek yönlü bir bağlantı" değildir. Bu yanlış yorumlayıcıyı basitçe alır çünkü '=' ifadesinden farklı olarak, herhangi bir $ saatler yaratmaz ve direktif kapsamındaki mülkün değerini değiştirmek ebeveyne yayılmaz.

Docs göre:

& veya & attr - bunu bir yönergede & kullandığınızda bağlamında ana kapsamını

bir ifade yürütmek için bir yol sağlar Üst kapsama göre değerlendirilen ifadenin değerini döndüren bir işlev oluşturur. İfadenin bir işlev çağrısı olması gerekmez. Herhangi bir geçerli açısal ifade olabilir. Buna ek olarak, bu oluşturulan işlev, ifadede bulunan herhangi bir yerel değişkenin değerini geçersiz kılan bir nesne argümanı alır. Eğer

foo({myVal: 42}); 

sana ne ararsanız, direktif (şablon veya bağlantı fonksiyonu) olarak

<my-component foo="go()"> 

:

ebeveyn varsayalım OP'ın örneğini genişletmek için aşağıdaki şekilde bu direktifini kullanır yapıyorsun "go()" ifadesini değerlendiriyor, bu da üst kapsamda "git" işlevini çağırıyor ve hiçbir argüman iletmiyor. Alternatif

,

<my-component foo="go(value)"> 

Temelde ($ parent.value)"

<my-component foo="go(myVal)"> 
$ parent.go çağırıyor olacak ebeveyn kapsamına ifadesi "go (değer)", değerlendiriyoruz

Sen ifadesi "go (MyVal)" değerlendiriyoruz ama ifade değerlendirilmeden önce, MyVal 42 ile değiştirilecek, böylece değerlendirilen ifadesi "(42) go" olacaktır.

<my-component foo="myVal + value + go()"> 
Bu durumda

, $ scope.foo ({MyVal: 42}) sonucunu döndürür: Esasen

42 + $parent.value + $parent.go() 

, bu desen yönergesi "enjekte" değişkenleri direktifin tüketici can buna izin verir isteğe bağlı olarak foo ifadesinde kullanın.

<my-component foo="go"> 

ve yönergede:

Bunu yapabilirsiniz

$scope.foo()(42) 

$ scope.foo() ifadesini değerlendirecek $ bir başvuru döndürür olan "go" parent.go işlevi. Daha sonra $ parent.go olarak adlandırılacaktır (42). Bu desenin olumsuz tarafı, ifadenin bir işlevi değerlendirmemesi durumunda bir hata alacağınızdır.

Aşağı oylamanın son nedeni, ng-event yönergelerinin & kullandığı iddiasıdır. Bu durum böyle değil.

$scope.foo = function(locals) { 
    return $parse(attr.foo)($scope.$parent, locals); 
} 

ng tıklama uygulanmasıdır:

scope:{ 
} 

(netlik için basitleştirilmiş) olan '& foo' uygulanması, aşağı kaynar: direktifleri inşa hiçbiri ile izole kapsamları oluşturmak benzer fakat (aynı zamanda basitleştirilmiş):

link: function(scope, elem, attr) { 
    elem.on('click', function(evt) { 
     $parse(attr.ngClick)(scope, { 
      $event: evt 
     } 
    }); 
} 

Yani hatırlamak için anahtar kullandığınızda '&', bir functio geçen olmamasıdır n - bir ifade iletiyorsunuz. Yönerge, üretilen ifadeyi çağırmak suretiyle bu ifadenin sonucunu herhangi bir zamanda alabilir.

+0

Neyi reddettiğimi haklı görmüyorum ve aynı sebepten aynısını yaptım. Tek yönlü sadece bir isim ama ben bir ifadeyi nasıl değerlendirdiğini açıklarım. Sen benim gibi tanıyorsun, $ scope.foo() (42) 'küçük bir anlam ifade eden bir anti-desen. Son olarak, 'ngRepeat' yalıtılmış bir kapsam oluşturmaz (ng-tıklama ve direktifte en yerleşik olanı, size kötü veririm), bu yüzden kullanıcı hala onun kapsamında önceden var olanı kullanabilir. Topluma daha iyi hizmet verebilmek için açıklamaları çoğaltmak yerine cevabımı düzenleyebilirdiniz. – floribon

+2

(düzeltme, bu oyunu oynamayı reddettim, bu oyunu oynatamıyorum) – floribon

+0

@JoeEnzminger Geçilen işlev bir tür geri arama ise? Yani "link" işlevinde belirtilen parametrelerle çağrılması gerekir. Bu durumda '=' kullanmak iyi mi? – kefir500

3

bir işlev geçmesine bağlanma İki yönlü sürece işlev her zaman aynı sırayla aynı parametreleri alacak kadar iyi. Ama bu amaç için de faydasız. bağlama

tek yönlü daha verimli ve herhangi bir parametre ile ve herhangi bir sırada bir işlev çağrısı ve HTML de görüş sunmasını sağlar. bazen daha karmaşık şeylere kadar böyle

<div ng-click="doStuff('hardcoded', var1+4); var2 && doAlso(var2)"> 

See olarak <div ng-click="doStuff(var1)"> gibi bir şey istiyorum: Mesela biz iki yönlü bağlayıcı olması ngClick hayal bile edemediğini HTML Parametreleri doğrudan manipüle edebilir.

Şimdi senin gibi tek yönlü bağlamaları nasıl kullanılacağı yanlış anlaşılmış hissediyorum. Eğer gerçekten sizin yönergede onFoo: '&' tanımlarsanız, o zaman bağlantı işlevinden sonra örneğin yapmalıyım:

// assume bar is already in your scope 
scope.bar = "yo"; 
// Now you can call foo like this 
scope.onFoo({extra: 42}); 

Yani HTML'nize size sadece tüm erişebilir

<div on-foo="doSomething(bar, extra)"> 

Not kullanabilirsiniz Direktifin izole kapsamının özellikleri (bar), aynı zamanda çağrı anında eklenen ekstra "yerliler" (extra).

scope.foo()(value) gibi Kişisel notasyonu bana kesmek gibi görünüyor, yani tek yönlü bağlamaları kullanmak itended yol değildir.

Not: tek yönlü bağlamaları tipik cevabı downvoted neden

İşte
+0

Bu neden azalıyor? Bunu yapan kişi, biraz fikir paylaşır mısınız? –

+0

Teşekkürler @Xavier_Ex, ben de bunun hakkında merak ediyorum. Eğer yanılıyorsam tam olarak ne olduğunu öğrenmek için hevesliyim. – floribon