Tautan vs kompilasi vs pengontrol

529

Saat Anda membuat arahan, Anda dapat memasukkan kode ke kompiler, fungsi tautan, atau pengontrol.

Dalam dokumen, mereka menjelaskan bahwa:

  • fungsi kompilasi dan tautan digunakan dalam berbagai fase siklus sudut
  • pengendali dibagi di antara arahan

Namun, bagi saya tidak jelas, kode seperti apa yang harus dituju.

Misalnya: Dapatkah saya membuat fungsi dalam kompilasi dan membuatnya dilampirkan ke lingkup di tautan atau hanya melampirkan fungsi ke lingkup di controller?

Bagaimana pengontrol dibagikan di antara arahan, jika setiap arahan dapat memiliki pengontrolnya sendiri? Apakah pengendali benar-benar dibagikan atau hanya properti lingkup?

schacki
sumber
11
Lihat juga stackoverflow.com/questions/12546945/…
Mark Rajcok
Mungkin gambaran yang lebih komprehensif dari fungsi direktif: Arahan arahan - kapan harus menggunakan kompilasi, controller, pra-tautan dan pasca-tautan .
Izhaki
1
Saya menulis posting dengan diagram siklus hidup direktif (tahap pembuatan). Mungkin itu membantu seseorang: filimanjaro.com/2014/...
rata

Jawaban:

470

Menyusun :

Ini adalah fase di mana Angular sebenarnya menyusun arahan Anda. Fungsi kompilasi ini dipanggil sekali saja untuk setiap referensi ke arahan yang diberikan. Misalnya, Anda menggunakan arahan ng-repeat. ng-repeat harus mencari elemen yang dilampirkan, mengekstrak fragmen html yang dilampirkan dan membuat fungsi template.

Jika Anda telah menggunakan HandleBar, garis bawah template atau yang setara, itu seperti mengkompilasi template mereka untuk mengekstrak fungsi template. Untuk fungsi templat ini, Anda meneruskan data dan nilai kembalinya fungsi tersebut adalah html dengan data di tempat yang tepat.

Fase kompilasi adalah langkah di Angular yang mengembalikan fungsi template. Fungsi template ini dalam sudut disebut fungsi menghubungkan.

Menghubungkan fase:

Fase penautan adalah tempat Anda melampirkan data ($ scope) ke fungsi penautan dan itu akan mengembalikan Anda html tertaut. Karena arahan juga menentukan ke mana html ini pergi atau apa yang berubah, itu sudah baik untuk pergi. Ini adalah fungsi tempat Anda ingin membuat perubahan pada html yang ditautkan, yaitu html yang sudah memiliki data terlampir padanya. Dalam sudut jika Anda menulis kode pada fungsi penautan, umumnya fungsi pasca-tautan (secara default). Ini semacam panggilan balik yang dipanggil setelah fungsi penautan telah menautkan data dengan templat.

Pengendali:

Pengontrol adalah tempat di mana Anda memasukkan beberapa logika spesifik direktif. Logika ini dapat masuk ke fungsi penghubung juga, tetapi kemudian Anda harus meletakkan logika itu pada ruang lingkup untuk membuatnya "dapat dibagikan". Masalah dengan itu adalah bahwa Anda kemudian akan merusak ruang lingkup dengan hal-hal arahan Anda yang tidak benar-benar sesuatu yang diharapkan. Jadi apa alternatifnya jika dua Arahan ingin berbicara satu sama lain / bekerja sama satu sama lain? Tentu Anda bisa memasukkan semua logika itu ke dalam layanan dan kemudian membuat kedua arahan ini bergantung pada layanan itu, tetapi itu hanya membawa satu ketergantungan lagi. Alternatifnya adalah menyediakan Pengendali untuk lingkup ini (biasanya mengisolasi ruang lingkup?) Dan kemudian pengontrol ini disuntikkan ke arahan lain ketika arahan itu "membutuhkan" yang lain.

Ganaraj
sumber
67
Untuk memperjelas: kompilasi kompilasi template yang akan digunakan di seluruh halaman. Linker terikat pada setiap instance. Baik? Kontroler kemudian bekerja di antara instance.
Zlatko
4
@ CMCDragonkai untuk setiap controllerfungsi direktif dijalankan setelah kompilasi, tetapi sebelumnya pre-link di cabang pohon DOM lokal. Juga controllerdan pre-linkfungsi yang dijalankan melintasi cabang DOM lokal dalam top-down cara. Setelah itu post-linkdieksekusi dengan cara bottom-up .
Artem Platonov
9
Hanya berantakan jika Anda tidak memahaminya. Ada alasan untuk melakukan apa yang dilakukannya.
demisx
3
Ini adalah jawaban teknis yang benar, namun, saya masih memiliki pertanyaan kapan saya harus menggunakan fungsi tautan.
Nicholas Marshall
2
Haruskah kita menggunakan controllerbukan di linkmana - mana? Jadi saya tidak perlu mengubah kode di masa depan jika metode ini perlu dibagi atau beberapa logika yang akan diperkenalkan ?. Apakah ada jebakan dalam menggunakan controllersepanjang waktu alih-alih tautan?
JPS
99

Saya ingin menambahkan juga apa yang dikatakan buku O'Reily AngularJS oleh Tim Google:

Pengontrol - Membuat pengontrol yang menerbitkan API untuk berkomunikasi di seluruh arahan. Contoh yang baik adalah Directive to Directive Communication

Tautan - Secara terprogram memodifikasi instance elemen DOM yang dihasilkan, menambahkan pendengar acara, dan mengatur pengikatan data.

Kompilasi - Secara terprogram memodifikasi templat DOM untuk fitur-fitur lintas salinan arahan, seperti ketika digunakan dalam ng-repeat. Fungsi kompilasi Anda juga dapat mengembalikan fungsi tautan untuk memodifikasi instance elemen yang dihasilkan.

Nicholas Dynan
sumber
Tautan thinkster.io Anda tidak dapat ditonton tanpa membayar. Bukan tautan saya, tapi mungkin ini lebih cocok: toddmotto.com/directive-to-directive-communication-with-require
R. van Twisk
51

A directivememungkinkan Anda untuk memperluas kosakata HTML secara deklaratif untuk membangun komponen web. The ng-appatribut direktif, jadi adalah ng-controllerdan semua ng- prefixed attributes. Arahan dapat attributes, tagsatau bahkan class names, comments.

Bagaimana arahan dilahirkan ( compilationdan instantiation)

Kompilasi: Kami akan menggunakan compilefungsi untuk kedua manipulateDOM sebelum diberikan dan mengembalikan linkfungsi (yang akan menangani tautan untuk kami). Ini juga tempat untuk meletakkan metode apa pun yang perlu dibagikan dengan semua instancesarahan ini.

tautan: Kami akan menggunakan linkfungsi ini untuk mendaftarkan semua pendengar pada elemen DOM tertentu (yang dikloning dari templat) dan mengatur ikatan kami ke halaman.

Jika diatur dalam compile()fungsi mereka hanya akan ditetapkan sekali (yang sering Anda inginkan). Jika diatur dalam link()fungsi mereka akan disetel setiap kali elemen HTML terikat ke data dalam objek.

<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){

     }
   };
});

Compilefungsi mengembalikan fungsi predan posttautan. Dalam fungsi pra tautan kami memiliki template contoh dan juga cakupan dari controller, tetapi template tersebut tidak terikat pada cakupan dan masih belum memiliki konten yang ditransklusikan.

Postfungsi tautan adalah tempat tautan pos adalah fungsi terakhir yang dijalankan. Sekarang transclusionselesai the template is linked to a scope,, dan view will update with data bound values after the next digest cycle. The linkpilihan adalah hanya jalan pintas untuk membuat sebuah post-linkfungsi.

controller: Controller directive dapat diteruskan ke fase penghubungan / kompilasi directive lainnya. Ini dapat disuntikkan ke arahan lain sebagai sarana untuk digunakan dalam komunikasi antar-direktif.

Anda harus menentukan nama arahan yang diperlukan - Ini harus terikat ke elemen yang sama atau induknya. Nama dapat diawali dengan:

?  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.

Gunakan braket persegi [‘directive1′, ‘directive2′, ‘directive3′]untuk memerlukan beberapa arahan pengontrol.

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
    }
  }
});
Thalaivar
sumber
1
Anda menyebutkan bahwa Anda menunjukkan cara memasukkan parentDirectiveCtrl ke controller anak ... contoh ini anak tidak memiliki controller, melainkan fungsi tautan ... Saya tidak terjebak pada masalah ini saat ini, jadi mungkin tidak sangat penting, tetapi pertanyaan yang aneh.
alockwood05
13

Selain itu, alasan yang baik untuk menggunakan fungsi pengontrol vs. tautan (karena keduanya memiliki akses ke ruang lingkup, elemen, dan attr) adalah karena Anda dapat meneruskan layanan atau ketergantungan yang tersedia ke pengontrol (dan dalam urutan apa pun), sedangkan Anda tidak dapat melakukannya dengan fungsi tautan. Perhatikan tanda tangan yang berbeda:

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

vs.

link: function(scope, element, attrs) {... //no services allowed
ScaryBunny
sumber
2
Silakan tinggalkan komentar untuk menjelaskan maksud Anda saat Anda memilih-pilih jawaban. Terima kasih
svassr
53
Saya tidak downvoter, tapi ini tidak sepenuhnya benar karena Anda masih dapat menyuntikkan setiap ketergantungan diperlukan ke dalam direktif itu sendiri, misalnya: module.directive('myDirective', function($window) { etc.... Ini kemudian dapat diakses dari dalam fungsi tautan.
Mike Chamberlain
1
ini kelihatannya tidak benar karena Anda dapat menyuntikkan layanan ke fungsi tautan
Code Whisperer
1
@JoshRibakoff Hasil akhirnya sama, Anda memiliki akses ke layanan dalam fungsi tautan. Tidak masalah apakah itu dinyatakan dalam argumen fungsi atau tidak. Dalam hal ini Mike Chamberlain benar
Connor Wyatt
1
@ cwyatt1 Saya mengoreksi bahasa, plnkr tidak menunjukkan fungsi menyuntikkan ke link () karena itu bukan fitur yang dimiliki Angular. Anda mungkin mengira saya sedang bertele-tele tetapi komentar metamatt sudah menguraikan banyak perbedaan penting antara apa yang dilakukan plunkr, dan apa yang disuntikkan ke controller. OP bertanya apa perbedaannya, dan ada perbedaan.
Josh Ribakoff
10

ini adalah contoh yang baik untuk memahami fase arahan 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>
Amin Rahimi
sumber
4
Bisakah Anda menguraikan mengapa kode sampel ini akan membantu untuk memahami perbedaan antara link, compiledan controller?
cel tajam
apakah Anda tahu bagaimana requiredirektif d dapat disuntikkan ke pengontrol direktif dependen?
alockwood05
Anda dapat mengambil contoh: Kesalahan Tidak Berhasil: [$ injector: modulerr] Gagal membuat modul myapp karena: Kesalahan: [$ injector: uns] Penyedia tidak dikenal: slngStylePrelinkProvider
rofrol
7
  • compile : digunakan ketika kita perlu memodifikasi template direktif, seperti menambahkan ekspresi baru, menambahkan direktif lain di dalam direktif ini
  • controller : digunakan ketika kita perlu membagikan / menggunakan kembali data $ scope
  • tautan : ini adalah fungsi yang digunakan ketika kita perlu melampirkan pengendali acara atau untuk memanipulasi DOM.
Hamidhan
sumber