Link vs derleme vs denetleyici


529

Bir yönerge oluşturduğunuzda, derleyiciye, link işlevine veya denetleyiciye kod koyabilirsiniz.

Dokümanlarda şunları açıklıyorlar:

  • Derleme ve bağlantı fonksiyonu açısal çevrimin farklı aşamalarında kullanılır
  • kontrolörler direktifler arasında paylaşılır

Ancak, benim için hangi tür kodların nereye gitmesi gerektiği belli değil.

Örnek: Derlemede işlevler oluşturabilir ve bağlantıdaki kapsama ekleyebilir miyim veya yalnızca denetleyicideki kapsama işlev ekleyebilir miyim?

Her direktifin kendi denetleyicisi olabilirse denetleyiciler direktifler arasında nasıl paylaşılır? Denetleyiciler gerçekten paylaşılıyor mu yoksa yalnızca kapsam özellikleri mi?



Belki de yönerge fonksiyonlarına daha kapsamlı bir genel bakış: Açısal direktifler - ne zaman derleme, kontrolör, ön link ve post link kullanılır .
Izhaki

1
Direktifin yaşam döngüsünü (oluşturma aşamasını) gösteren bir yazı yazdım. Belki de birine yardımcı olur: filimanjaro.com/2014/…
ortalama Joe

Yanıtlar:


470

Derleme:

Bu, Angular'ın direktifinizi derlediği aşamadır. Bu derleme işlevi, verilen yönergeye yapılan her başvuru için yalnızca bir kez çağrılır. Örneğin, ng-yineleme yönergesini kullandığınızı varsayalım. ng-repeat, bağlı olduğu elemanı aramalı, bağlı olduğu html parçasını çıkarmalı ve bir şablon fonksiyonu yaratmalıdır.

Gidon, alt çizgi şablonları veya eşdeğeri kullandıysanız, şablon işlevini ayıklamak için şablonlarını derleme gibi. Bu şablon işlevine veri iletirsiniz ve bu işlevin dönüş değeri, verileri doğru yerlerde içeren html'dir.

Derleme aşaması, Angular'da şablon işlevini döndüren adımdır. Açısal olan bu şablon işlevine bağlantı işlevi denir.

Bağlantı aşaması:

Bağlama aşaması, bağlama işlevine verileri ($ scope) eklediğiniz yerdir ve size bağlı html'yi döndürmelidir. Yönerge ayrıca bu html'nin nereye gittiğini veya neyi değiştirdiğini belirttiğinden, zaten gitmek iyidir. Bu, bağlı html'de, yani zaten kendisine veri eklenmiş olan html'de değişiklik yapmak istediğiniz işlevdir. Bağlama işlevinde kod yazarsanız açısal olarak, genellikle bağlantı sonrası işlevi (varsayılan olarak). Bu, bağlantı işlevi verileri şablona bağladıktan sonra çağrılan bir geri arama türüdür.

Denetleyici:

Denetleyici bazı direktiflere özgü mantık koyduğunuz bir yerdir. Bu mantık aynı zamanda bağlama fonksiyonuna da girebilir, ancak daha sonra "paylaşılabilir" hale getirmek için o mantığı kapsama koymanız gerekir. Sorun şu ki, kapsamı gerçekten beklenen bir şey olmayan direktiflerinizle bozuyorsunuz. Peki iki Direktif birbiriyle konuşmak / birbirleriyle işbirliği yapmak istiyorsa alternatif nedir? Tabii ki tüm bu mantığı bir hizmete koyabilir ve sonra her iki yönergeyi de bu hizmete bağımlı hale getirebilirsiniz, ancak bu sadece bir bağımlılık getirir. Alternatif, bu kapsam için bir Kontrolör sağlamaktır (genellikle kapsamı izole eder?) Ve daha sonra bu kontrolör, diğerini "gerektirdiğinde" başka bir direktif içine enjekte edilir.


67
Açıklığa kavuşturmak için: compile sayfa boyunca kullanılacak şablonu derler. Bağlayıcı her örneğe bağlıdır. Sağ? Daha sonra Controller örnekler arasında çalışır.
Zlatko

4
Her yönerge controllerişlevi için @CMCDragonkai derlemeden sonra , ancak daha önce pre-link yerel bir DOM ağacı dalında yürütülür . Ayrıca controllerve pre-linkyerel DOM dalını yukarıdan aşağıya doğru hareket eden işlevler yürütülür . Bundan sonra aşağıdan yukarıya bir şekilde post-linkyürütülür .
Artem Platonov

9
Eğer anlamıyorsan sadece bir karmaşa. Yaptığı şeyi yapmasının bir nedeni var.
demisx

3
Bu doğru teknik cevaptır, ancak yine de link işlevini ne zaman kullanmam gerektiğine dair sorularım var.
Nicholas Marshall

2
Her yer controlleryerine kullanalım linkmı? Böylece yöntem paylaşılması gerekiyorsa veya bazı mantık tanıtılması gerekiyorsa gelecekte kodu değiştirmek gerekmez ?. controllerBağlantı yerine sürekli kullanımda herhangi bir tuzak var mı ?
JPS

99

Google Ekibi'nin O'Reily AngularJS kitabının söylediklerini de eklemek istedim:

Denetleyici - Yönergeler arasında iletişim için bir API yayınlayan bir denetleyici oluşturun. İyi bir örnek Direktif İletişim Direktifidir

Bağlantı - Ortaya çıkan DOM öğesi örneklerini programlı olarak değiştirme, olay dinleyicileri ekleme ve veri bağlama ayarlama.

Derle - Bir yönergenin kopyaları arasında yer alan özellikler için DOM şablonunu, ng tekrarında kullanıldıkları gibi programatik olarak değiştirin. Derleme işleviniz, sonuçta ortaya çıkan öğe örneklerini değiştirmek için bağlantı işlevlerini de döndürebilir.


Thinkster.io bağlantınız ödemeden izlenemez. Bağlantım değil, ama belki de daha uygun: toddmotto.com/directive-to-directive-communication-with-require
R. van Twisk

51

A directive, HTML bileşenlerini web bileşenleri oluşturmak için bildirici bir şekilde genişletmenizi sağlar. ng-appÖznitelik bir yönerge, bu nedenle olduğunu ng-controllerve tüm ng- prefixed attributes. Direktifleri olabilir attributes, tagshatta ya class names,comments .

Direktiflerin doğuşu ( compilationve instantiation)

Derleme: Biz kullanacağız compilehem fonksiyon manipulateo hale edilmeden önce DOM ve dönüş linkfonksiyonu (bizim için bağlama idare edecek). Burası aynı zamanda instancesbu direktifin tamamı ile paylaşılması gereken herhangi bir yöntemi koyabileceğiniz yerdir .

link: Biz kullanacağız link(şablondan kopyalamış) ve sayfaya bizim bağlantıları kurmak belirli DOM öğesindeki tüm dinleyicileri kayıt fonksiyonu.

İşlevde ayarlanırsa, compile()yalnızca bir kez ayarlanmış olurlar (bu genellikle istediğiniz şeydir). İşlevde ayarlanırsa link(), HTML öğesi nesnedeki verilere her bağlandığında ayarlanırlar .

<div ng-repeat="i in [0,1,2]">
    <simple>
        <div>Inner content</div>
    </simple>
</div>

app.directive("simple", function(){
   return {
     restrict: "EA",
     transclude:true,
     template:"<div>{{label}}<div ng-transclude></div></div>",        
     compile: function(element, attributes){  
     return {
             pre: function(scope, element, attributes, controller, transcludeFn){

             },
             post: function(scope, element, attributes, controller, transcludeFn){

             }
         }
     },
     controller: function($scope){

     }
   };
});

Compileişlevi preve postbağlantı işlevini döndürür . Ön bağlantı işlevinde örnek şablonuna ve kapsamından da sahibiz controller, ancak yine de şablon kapsama bağlı değildir ve yine de kopyalanmış içeriğe sahip değildir.

Postlink işlevi post link'in yürütülecek son işlev olduğu yerdir. Şimdi transclusiontamamlandı the template is linked to a scope, ve view will update with data bound values after the next digest cycle. linkSeçenek kurma için sadece bir kısa yoldur post-linkişlevi.

denetleyici: Yönerge denetleyicisi başka bir yönerge bağlama / derleme aşamasına geçirilebilir. Direktifler arası iletişimde kullanılması için diğer yönlendirmelere enjekte edilebilir.

Gerekli direktifin adını belirtmelisiniz - Aynı öğeye veya üst öğeye bağlı olmalıdır. Adın önüne ön ek yapılabilir:

?  Will not raise any error if a mentioned directive does not exist.
^  Will look for the directive on parent elements, if not available on the same element.

[‘directive1′, ‘directive2′, ‘directive3′]Birden fazla yönerge denetleyicisi gerektirmek için köşeli ayraç kullanın .

var app = angular.module('app', []);

app.controller('MainCtrl', function($scope, $element) {
});

app.directive('parentDirective', function() {
  return {
    restrict: 'E',
    template: '<child-directive></child-directive>',
    controller: function($scope, $element){
      this.variable = "Hi Vinothbabu"
    }
  }
});

app.directive('childDirective', function() {
  return {
    restrict:  'E',
    template: '<h1>I am child</h1>',
    replace: true,
    require: '^parentDirective',
    link: function($scope, $element, attr, parentDirectCtrl){
      //you now have access to parentDirectCtrl.variable
    }
  }
});

1
parentDirectiveCtrl öğesini çocuğun denetleyicisine nasıl alacağınızı gösterdiğinizden bahsettiniz ... bu örnekte çocuğun denetleyicisi yok, daha çok bağlantı işlevi var ... Şu anda bu konuda takılı kalmam, bu yüzden olmayabilir çok önemli, ama meraklı bir soru.
alockwood05

13

Ayrıca, denetleyici ve bağlantı işlevini kullanmak için iyi bir neden (her ikisinin de kapsam, öğe ve izinlere erişimi olduğu için), kullanılabilir herhangi bir hizmeti veya bağımlılığı bir denetleyiciye (ve herhangi bir sırada) geçirebilmenizdir. bunu link işlevi ile yapamazsınız. Farklı imzalara dikkat edin:

controller: function($scope, $exceptionHandler, $attr, $element, $parse, $myOtherService, someCrazyDependency) {...

vs.

link: function(scope, element, attrs) {... //no services allowed

2
Lütfen bir cevabı indirdiğinizde dikkatinizi açıklamak için bir yorum bırakın. Teşekkürler
svassr

53
Ben downvoter değildi, ama yine de direktif üzerine, örneğin herhangi gerekli bağımlılığa enjekte çünkü bu kesinlikle doğru değil: module.directive('myDirective', function($window) { etc.... Bu daha sonra link fonksiyonunun içinden erişilebilir.
Mike Chamberlain

1
Bu bağlantı işlevi içine hizmet enjekte gibi bu açıkça yanlış görünüyor
Code Whisperer

1
@JoshRibakoff Sonuç aynıdır, link işlevinde servise erişiminiz olur. İşlevin argümanlarında bildirilip bildirilmemesi önemli değildir. Bu bağlamda Mike Chamberlain doğrudur
Connor Wyatt

1
@ cwyatt1 Parlance düzeliyordum, plnkr bir link () fonksiyonuna enjekte edilmiyor çünkü Angular'ın sahip olduğu bir özellik değil. Bilgiçlik hissettiğimi düşünebilirsiniz, ancak metamatt yorumları zaten plunkr'ın yaptığı ve bir denetleyiciye enjekte ettikleri arasındaki sayısız önemli farklılığı özetliyor. OP, farklılıkların ne olduğunu soruyor ve farklılıklar var.
Josh Ribakoff

10

Bu, yönerge aşamalarını anlamak için iyi bir örnektir http://codepen.io/anon/pen/oXMdBQ?editors=101

var app = angular.module('myapp', [])

app.directive('slngStylePrelink', function() {
    return {
        scope: {
            drctvName: '@'
        },
        controller: function($scope) {
            console.log('controller for ', $scope.drctvName);
        },
        compile: function(element, attr) {
            console.log("compile for ", attr.name)
            return {
                post: function($scope, element, attr) {
                    console.log('post link for ', attr.name)
                },
                pre: function($scope, element, attr) {
                    $scope.element = element;
                    console.log('pre link for ', attr.name)
                        // from angular.js 1.4.1
                    function ngStyleWatchAction(newStyles, oldStyles) {
                        if (oldStyles && (newStyles !== oldStyles)) {
                            forEach(oldStyles, function(val, style) {
                                element.css(style, '');
                            });
                        }
                        if (newStyles) element.css(newStyles);
                    }

                    $scope.$watch(attr.slngStylePrelink, ngStyleWatchAction, true);

                    // Run immediately, because the watcher's first run is async
                    ngStyleWatchAction($scope.$eval(attr.slngStylePrelink));
                }
            };
        }
    };
});

html

<body ng-app="myapp">
    <div slng-style-prelink="{height:'500px'}" drctv-name='parent' style="border:1px solid" name="parent">
        <div slng-style-prelink="{height:'50%'}" drctv-name='child' style="border:1px solid red" name='child'>
        </div>
    </div>
</body>

4
Bu örnek kodun link, compileve arasındaki farkı anlamasına neden yardımcı olacağını açıklayabilir misiniz controller?
cel sharp

Bir requiredirektifin bağımlı direktifin kontrolörüne nasıl enjekte edilebileceğini biliyor musunuz ?
alockwood05

Kod örneği örneği: Yakalanmadı Hata: [$ injector: modulerr] Aşağıdaki nedenlerden dolayı modül myappı başlatılamadı: Hata: [$ injector: unpr] Bilinmeyen sağlayıcı: slngStylePrelinkProvider
rofrol

7
  • compile : yönerge şablonunu değiştirmemiz gerektiğinde kullanılır, örneğin yeni ifade ekle, bu direktifin içine başka bir direktif ekleyin
  • denetleyici : $ kapsam verilerini paylaşmamız / yeniden kullanmamız gerektiğinde kullanılır
  • link : olay işleyici eklememiz veya DOM'u manipüle etmemiz gerektiğinde kullanılan bir fonksiyondur.
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.