Apa perbedaan antara '@' dan '=' dalam lingkup direktif dalam AngularJS?

1067

Saya sudah membaca dokumentasi AngularJS tentang topik itu dengan hati-hati, dan kemudian mengutak-atik arahan. Ini biola .

Dan berikut ini beberapa cuplikan yang relevan:

  • Dari HTML :

    <pane bi-title="title" title="{{title}}">{{text}}</pane>
  • Dari arahan panel:

    scope: { biTitle: '=', title: '@', bar: '=' },

Ada beberapa hal yang tidak saya dapatkan:

  • Mengapa saya harus menggunakan "{{title}}"dengan '@'dan "title"dengan '='?
  • Bisakah saya juga mengakses ruang lingkup induk secara langsung, tanpa mendekorasi elemen saya dengan atribut?
  • Dokumentasi mengatakan "Seringkali diinginkan untuk meneruskan data dari ruang lingkup terisolasi melalui ekspresi dan ke ruang lingkup induk" , tetapi itu tampaknya berfungsi dengan baik dengan pengikatan dua arah juga. Mengapa rute ekspresi lebih baik?

Saya menemukan biola lain yang menunjukkan solusi ekspresi juga: http://jsfiddle.net/maxisam/QrCXh/

iwein
sumber
18
Titik adil. Kemampuan untuk meneliti dan menemukan jawaban adalah penting.
Jonathan
1
Dengan kata =- kata sederhana digunakan dalam lingkup isolasi direktif untuk mengaktifkan ikatan dua arah dan @tidak memperbarui model, hanya memperbarui nilai-nilai ruang lingkup Direktif.
STEEL
@ iwein mengapa kode biola Anda di jsfiddle.net/maxisam/QrCXh tidak berfungsi dengan googleapi - ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js ? Kode Anda hanya berfungsi jika saya menggunakan cdn Anda - code.angularjs.org/1.0.1/angular-1.0.1.js
MukulSharma
Saya melihat banyak jawaban bagus di bawah ini, tetapi adakah yang bisa memberikan petunjuk ke dokumentasi sudut resmi yang menjawab pertanyaan ini?
John Henckel

Jawaban:

1151

Mengapa saya harus menggunakan "{{title}}" dengan ' @ ' dan "title" dengan ' = '?

@ mengikat properti lingkup direktif lokal / ke nilai yang dievaluasi dari atribut DOM . Jika Anda menggunakan title=title1atau title="title1", nilai atribut "judul" DOM ​​hanyalah string title1. Jika Anda menggunakan title="{{title}}", nilai atribut "judul" DOM ​​adalah nilai yang diinterpolasi {{title}}, maka string tersebut akan menjadi apa pun yang dimiliki properti judul "induk" lingkup saat ini. Karena nilai atribut selalu berupa string, Anda akan selalu berakhir dengan nilai string untuk properti ini dalam ruang lingkup direktif saat menggunakan @ .

= mengikat properti lingkup lokal / direktif ke properti lingkup induk . Jadi dengan = , Anda menggunakan nama properti model / lingkup orangtua sebagai nilai atribut DOM. Anda tidak dapat menggunakan {{}}s dengan = .

Dengan @, Anda dapat melakukan hal-hal seperti title="{{title}} and then some"- {{title}} diinterpolasi, kemudian string "dan mereka beberapa" disatukan dengannya. String gabungan terakhir adalah apa yang didapat properti lingkup direktif lokal /. (Anda tidak dapat melakukan ini dengan = , hanya @ .)

Dengan @ , Anda harus menggunakan attr.$observe('title', function(value) { ... })jika Anda perlu menggunakan nilai dalam fungsi tautan Anda. Misalnya, if(scope.title == "...")tidak akan berfungsi seperti yang Anda harapkan. Perhatikan bahwa ini berarti Anda hanya dapat mengakses atribut ini secara tidak sinkron . Anda tidak perlu menggunakan $ mengamati () jika Anda hanya menggunakan nilai dalam templat. Misalnya template: '<div>{{title}}</div>',.

Dengan = , Anda tidak perlu menggunakan $ mengamati.

Bisakah saya juga mengakses ruang lingkup induk secara langsung, tanpa mendekorasi elemen saya dengan atribut?

Ya, tetapi hanya jika Anda tidak menggunakan lingkup isolasi. Hapus baris ini dari arahan Anda

scope: { ... }

dan kemudian arahan Anda tidak akan membuat ruang lingkup baru. Ini akan menggunakan lingkup induk. Anda kemudian dapat mengakses semua properti lingkup induk secara langsung.

Dokumentasi mengatakan "Seringkali diinginkan untuk meneruskan data dari ruang lingkup terisolasi melalui ekspresi dan ke ruang lingkup induk", tetapi itu tampaknya berfungsi dengan baik dengan pengikatan dua arah juga. Mengapa rute ekspresi lebih baik?

Ya, pengikatan dua arah memungkinkan lingkup lokal / direktif dan cakupan induk untuk berbagi data. "Pengikatan ekspresi" memungkinkan arahan untuk memanggil ekspresi (atau fungsi) yang didefinisikan oleh atribut DOM - dan Anda juga dapat meneruskan data sebagai argumen untuk ekspresi atau fungsi tersebut. Jadi, jika Anda tidak perlu berbagi data dengan induk - Anda hanya ingin memanggil fungsi yang didefinisikan dalam lingkup induk - Anda dapat menggunakan & sintaks.

Lihat juga

Mark Rajcok
sumber
1
Huh, ini adalah perilaku yang sangat aneh, terutama ketika tidak menggunakan interpolasi dan hanya mencoba untuk melewati sebuah string. Rupanya permintaan tarikan memang telah bergabung ke dalam pengembangan pembangunan dan berada di 1.1.5 dan 1.2.0 RC membangun. Bagus untuk mereka memperbaiki perilaku yang sangat tidak intuitif ini!
Ibrahim
50
Menulis '@' atau '=' jauh lebih jelas daripada menulis "eval-dom" atau "parent-scope" atau teks lain yang bisa dibaca manusia. Keputusan desain yang bagus.
Den
13
@('at') menyalin nilai dari 'ATtribute'. =('sama dengan') sama dengan mengatakan kunci sama dengan ekspresi Anda. Setidaknya, begitulah cara saya menjaga mereka.
Matt DeKrey
1
Apakah Anda yakin bahwa = hanya untuk properti lingkup-induk? Ekspresi apa pun tampaknya berfungsi - tidak hanya properti lingkup orangtua.
Jonathan Aquino
4
@JonathanAquino, ya itu berfungsi, tapi @ akan lebih sesuai - dengan foo="{{1+1}}"- karena kita tidak perlu pengikatan data dua arah di sini. Poin yang saya coba buat dalam komentar di atas adalah bahwa kita harus menggunakan = hanya ketika direktif membutuhkan pengikatan data dua arah. Gunakan @ atau & sebaliknya.
Mark Rajcok
542

Ada banyak jawaban yang besar di sini, tapi saya ingin menawarkan perspektif saya tentang perbedaan antara @, =dan &mengikat yang terbukti berguna bagi saya.

Ketiga ikatan ini adalah cara meneruskan data dari ruang lingkup orang tua Anda ke ruang lingkup terarah direktif Anda melalui atribut elemen:

  1. @ binding adalah untuk melewatkan string. String ini mendukung {{}}ekspresi untuk nilai interpolasi. Sebagai contoh: . Ekspresi interpolasi dievaluasi terhadap lingkup induk direktif.

  2. = binding adalah untuk model mengikat dua arah. Model dalam lingkup induk terkait dengan model dalam lingkup terisolasi direktif. Perubahan ke satu model memengaruhi yang lain, dan sebaliknya.

  3. & binding adalah untuk meneruskan metode ke dalam lingkup direktif Anda sehingga dapat dipanggil dalam arahan Anda. Metode ini terikat sebelumnya dengan ruang lingkup induk direktif, dan mendukung argumen. Misalnya jika metode ini hello (nama) dalam lingkup induk, maka untuk mengeksekusi metode dari dalam arahan Anda, Anda harus memanggil $ scope.hello ({name: 'world'})

Saya menemukan bahwa lebih mudah untuk mengingat perbedaan-perbedaan ini dengan merujuk pada cakupan lingkup dengan deskripsi yang lebih pendek:

  • @ Atribut string binding
  • = Penjilidan model dua arah
  • & Penjilidan metode panggilan balik

Simbol juga memperjelas apa yang dilambangkan oleh variabel lingkup di dalam implementasi arahan Anda:

  • @ tali
  • = model
  • & metode

Dalam urutan kegunaan (bagi saya bagaimanapun):

  1. =
  2. @
  3. &
pixelbits
sumber
13
Sebenarnya, "&"apakah mendukung argumen (atau, lebih tepatnya, penduduk setempat) dari bentuk:, callback({foo: "some value"})yang kemudian dapat digunakan <my-dir callback="doSomething(foo)">. Jika tidak, jawaban yang baik
Dev Baru
11
Harus diterima jawaban. Berikut ini adalah artikel ringkas dengan informasi yang sama, tetapi dengan contoh kode tambahan: berumur.io/…
Kevin
4
& BUKAN "Metode panggilan balik mengikat", ini adalah pengikatan ekspresi sudut. Contoh khusus tetapi bukan satu-satunya adalah ekspresi callback(argument). Yang masih tidak sama dengan callbackdirinya sendiri.
Dmitri Zaitsev
14
Sementara saya suka bagaimana definitif jawaban peringkat yang lebih tinggi, saya menemukan ini membuat dampak yang lebih bermanfaat dan setelah membaca yang ini saya lebih memahami jawaban sebelumnya.
rbnzdave
1
Saya setuju dengan komentar di atas, jawaban ini lebih jelas, pasti dan bermanfaat untuk pertanyaan. Ini menjelaskan dengan cukup detail sehingga Anda dapat pergi dan menggunakan informasi tersebut.
user3125823
64

The =berarti bi-directional mengikat, sehingga referensi ke variabel ke lingkup induk. Ini berarti, ketika Anda mengubah variabel dalam arahan, itu akan berubah dalam lingkup induk juga.

@ berarti variabel akan disalin (dikloning) ke dalam direktif.

Sejauh yang saya tahu, <pane bi-title="{{title}}" title="{{title}}">{{text}}</pane>harus bekerja juga. bi-titleakan menerima nilai variabel lingkup induk, yang dapat diubah dalam arahan.

Jika Anda perlu mengubah beberapa variabel dalam lingkup induk, Anda bisa menjalankan fungsi pada lingkup induk dari dalam direktif (atau meneruskan data melalui layanan).

Asgoth
sumber
1
Ya, bagian yang saya dapatkan, lihat biola dalam pertanyaan. Tetapi bagaimana dengan bagian yang tidak jelas?
iwein
4
masalahnya {{}} tidak berfungsi dengan =. = tidak dievaluasi, tetapi string diambil sebagai nama properti apa adanya. Terima kasih atas jawabannya!
iwein
1
Saya tidak berpikir bahwa = hanya untuk variabel dalam lingkup induk. Ini bekerja dengan ekspresi apa pun (misalnya, 1 + 1).
Jonathan Aquino
1
@JonathanAquino Anda benar karena mengevaluasi ekspresi. imho ini sebenarnya aneh dan saya tidak akan menggunakannya seperti itu. Trik cerdik semacam inilah yang membuat ruang lingkup pengarahan sulit bagi saya untuk memahaminya.
iwein
1
Apakah saya satu-satunya yang berpikir jawaban ini salah! '=' Berarti sudut mengharapkan ekspresi javascript dan akan melakukan pemetaan bidirectionnal jika variabel lingkup dilewatkan. Sedangkan @ berarti sudut mengharapkan String dan itu semua. Bahkan, memang benar bahwa jika Anda menggunakan @ dalam kombinasi dengan {{}} Anda akan mengkloning nilai variabel. Tapi itu bukan definisi @!
Luc DUZAN
39

Jika Anda ingin melihat lebih lanjut bagaimana ini bekerja dengan contoh langsung. http://jsfiddle.net/juanmendez/k6chmnch/

var app = angular.module('app', []);
app.controller("myController", function ($scope) {
    $scope.title = "binding";
});
app.directive("jmFind", function () {
    return {
        replace: true,
        restrict: 'C',
        transclude: true,
        scope: {
            title1: "=",
            title2: "@"
        },
        template: "<div><p>{{title1}} {{title2}}</p></div>"
    };
});
Juan Mendez
sumber
2
Ada beberapa contoh yang terkait dalam pertanyaan dan jawaban teratas. Apa yang ini tambahkan?
iwein
10
@ iwein, ini menambah kejelasan. Jika saya dapat memahami dan mengasimilasi contoh fitur lengkap, saya tidak akan memerlukan situs ini.
Tony Ennis
3
juan, mungkin memperbaiki kesalahan ketik Anda? 'transclude' salah eja. lebih baik lagi, hapus (dan yang lainnya, seperti 'ganti') yang tidak berkontribusi langsung ke masalah sehingga solusi Anda bahkan lebih sederhana dan lebih jelas. +1 sebagai contoh.
Tony Ennis
terima kasih @AnikISlamAbhi untuk mengedit. Saya ingin berkontribusi lebih banyak dan saya senang beberapa sampel saya bermanfaat. Itulah tujuan utamanya.
Juan Mendez
Contoh tidak lengkap. Dalam demonstrasi Anda, Anda hanya mengubah nilai dua arah. Anda bahkan tidak mencoba mengubah nilai yang memiliki ruang lingkup yang terisolasi. Jadi, itu tidak menunjukkan dengan baik bagaimana ruang lingkup bekerja dalam arahan.
Sudarshan_SMD
38

@ dapatkan sebagai string

  • Ini tidak membuat ikatan apa pun. Anda hanya mendapatkan kata yang Anda berikan sebagai string

= 2 cara mengikat

  • perubahan yang dilakukan dari pengontrol akan tercermin dalam referensi yang dipegang oleh arahan, dan sebaliknya

&Ini berperilaku sedikit berbeda, karena ruang lingkup mendapat fungsi yang mengembalikan objek yang dilewatkan . Saya berasumsi ini diperlukan untuk membuatnya bekerja. Biola harus menjelaskan ini.

  • Setelah memanggil fungsi pengambil ini, objek yang dihasilkan berperilaku sebagai berikut:
    • jika suatu fungsi disahkan: maka fungsi tersebut dieksekusi dalam penutupan induk (pengontrol) saat dipanggil
    • jika non-fungsi diteruskan: cukup dapatkan salinan lokal dari objek yang tidak memiliki binding


Biola ini harus menunjukkan cara kerjanya . Berikan perhatian khusus pada fungsi ruang lingkup dengan get...namanya untuk semoga lebih memahami apa yang saya maksud&

Geg
sumber
36

Ada tiga cara ruang lingkup dapat ditambahkan dalam arahan:

  1. Lingkup induk : Ini adalah bawaan lingkup bawaan.

Direktif dan induknya (controller / direktif di dalamnya terletak) cakupannya sama. Jadi setiap perubahan yang dilakukan pada variabel lingkup di dalam direktif tercermin dalam pengontrol induk juga. Anda tidak perlu menentukan ini karena ini adalah default.

  1. Lingkup anak : direktif menciptakan ruang lingkup anak yang mewarisi dari lingkup induk jika Anda menentukan variabel ruang lingkup direktif sebagai benar.

Di sini, jika Anda mengubah variabel lingkup di dalam direktif, itu tidak akan mencerminkan dalam lingkup induk, tetapi jika Anda mengubah properti variabel lingkup, yang tercermin dalam lingkup induk, saat Anda benar-benar mengubah variabel lingkup induk .

Contoh,

app.directive("myDirective", function(){

    return {
        restrict: "EA",
        scope: true,
        link: function(element, scope, attrs){
            scope.somvar = "new value"; //doesnot reflect in the parent scope
            scope.someObj.someProp = "new value"; //reflects as someObj is of parent, we modified that but did not override.
        }
    };
});
  1. Ruang lingkup terisolasi : Ini digunakan ketika Anda ingin membuat ruang lingkup yang tidak mewarisi dari ruang lingkup pengontrol.

Ini terjadi ketika Anda membuat plugin karena ini membuat direktif generik karena dapat ditempatkan di HTML apa pun dan tidak terpengaruh oleh ruang lingkup induknya.

Sekarang, jika Anda tidak ingin interaksi dengan lingkup induk, maka Anda bisa menentukan lingkup sebagai objek kosong. Suka,

scope: {} //this does not interact with the parent scope in any way

Sebagian besar ini tidak terjadi karena kami memerlukan beberapa interaksi dengan ruang lingkup induk, jadi kami ingin beberapa nilai / perubahan dilewati. Untuk alasan ini, kami menggunakan:

1. "@"   (  Text binding / one-way binding )
2. "="   ( Direct model binding / two-way binding )
3. "&"   ( Behaviour binding / Method binding  )

@ berarti bahwa perubahan dari lingkup pengontrol akan tercermin dalam cakupan direktif tetapi jika Anda mengubah nilai dalam cakupan direktif, variabel lingkup pengontrol tidak akan terpengaruh.

@ selalu mengharapkan atribut yang dipetakan menjadi ekspresi. Ini sangat penting; karena untuk membuat awalan “@” berfungsi, kita perlu membungkus nilai atribut di dalam {{}}.

= adalah dua arah jadi jika Anda mengubah variabel dalam ruang lingkup direktif, variabel ruang lingkup pengontrol juga akan terpengaruh

& digunakan untuk mengikat metode lingkup pengontrol sehingga jika diperlukan kita dapat memanggilnya dari direktif

Keuntungannya di sini adalah bahwa nama variabel tidak harus sama dalam lingkup pengontrol dan ruang lingkup direktif.

Contoh, ruang lingkup direktif memiliki variabel "dirVar" yang disinkronkan dengan variabel "contVar" dari ruang lingkup pengontrol. Ini memberikan banyak daya dan generalisasi ke direktif karena satu pengontrol dapat disinkronkan dengan variabel v1 sementara pengontrol lain yang menggunakan arahan yang sama dapat meminta dirVar untuk melakukan sinkronisasi dengan variabel v2.

Di bawah ini adalah contoh penggunaan:

Arahan dan pengontrol adalah:

 var app = angular.module("app", []);
 app.controller("MainCtrl", function( $scope ){
    $scope.name = "Harry";
    $scope.color = "#333333";
    $scope.reverseName = function(){
     $scope.name = $scope.name.split("").reverse().join("");
    };
    $scope.randomColor = function(){
        $scope.color = '#'+Math.floor(Math.random()*16777215).toString(16);
    };
});
app.directive("myDirective", function(){
    return {
        restrict: "EA",
        scope: {
            name: "@",
            color: "=",
            reverse: "&"
        },
        link: function(element, scope, attrs){
           //do something like
           $scope.reverse(); 
          //calling the controllers function
        }
    };
});

Dan html (perhatikan perbedaan untuk @ dan =):

<div my-directive
  class="directive"
  name="{{name}}"
  reverse="reverseName()"
  color="color" >
</div>

Berikut ini tautan ke blog yang menggambarkannya dengan baik.

Kop4lyf
sumber
& bukan "Pengikatan tingkah laku" atau "Pengikatan metode", ini adalah pengikatan ekspresi sudut.
Dmitri Zaitsev
20

Cukup kita bisa menggunakan: -

  1. @ : - untuk nilai String untuk pengikatan data satu arah. dalam satu cara pengikatan data, Anda hanya bisa meneruskan nilai ruang lingkup ke arahan

  2. = : - untuk nilai objek untuk pengikatan data dua arah. dalam pengikatan data dua arah Anda dapat mengubah nilai ruang lingkup dalam direktif serta di html juga.

  3. & : - untuk metode dan fungsi.

EDIT

Dalam definisi Komponen kami untuk Angular versi 1.5 Dan di atas
ada empat jenis binding:

  1. = Pengikatan data dua arah : - jika kita mengubah nilainya, secara otomatis akan diperbarui
  2. < satu cara mengikat : - ketika kita hanya ingin membaca parameter dari lingkup induk dan tidak memperbaruinya.

  3. @ini untuk Parameter Parameter

  4. &ini untuk Callback jika komponen Anda perlu menampilkan sesuatu ke lingkup induknya

ojus kulkarni
sumber
13

Saya membuat file HTML kecil yang berisi kode sudut yang menunjukkan perbedaan di antara mereka:

<!DOCTYPE html>
<html>
  <head>
    <title>Angular</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
  </head>
  <body ng-app="myApp">
    <div ng-controller="myCtrl as VM">
      <a my-dir
        attr1="VM.sayHi('Juan')" <!-- scope: "=" -->
        attr2="VM.sayHi('Juan')" <!-- scope: "@" -->
        attr3="VM.sayHi('Juan')" <!-- scope: "&" -->
      ></a>
    </div>
    <script>
    angular.module("myApp", [])
    .controller("myCtrl", [function(){
      var vm = this;
      vm.sayHi = function(name){
        return ("Hey there, " + name);
      }
    }])
    .directive("myDir", [function(){
      return {
        scope: {
          attr1: "=",
          attr2: "@",
          attr3: "&"
        },
        link: function(scope){
          console.log(scope.attr1);   // =, logs "Hey there, Juan"
          console.log(scope.attr2);   // @, logs "VM.sayHi('Juan')"
          console.log(scope.attr3);   // &, logs "function (a){return h(c,a)}"
          console.log(scope.attr3()); // &, logs "Hey there, Juan"
        }
      }
    }]);
    </script>
  </body>
</html>
RobertAKARobin
sumber
6

The = cara adalah 2-arah yang mengikat , yang memungkinkan Anda untuk memiliki hidup perubahan di dalam direktif Anda. Ketika seseorang mengubah variabel itu dari arahan, Anda akan memiliki data yang berubah di dalam arahan Anda, tetapi @ way tidak mengikat dua arah . Ini berfungsi seperti Teks . Anda mengikat sekali, dan Anda hanya akan memiliki nilainya.

Untuk membuatnya lebih jelas, Anda dapat menggunakan artikel hebat ini:

Lingkup Petunjuk AngularJS '@' dan '='

Hazarapet Tunanyan
sumber
6

Pertanyaan ini sudah dipukuli sampai mati, tetapi saya akan tetap membagikannya kalau-kalau ada orang di luar sana yang berjuang dengan kekacauan mengerikan yang menjadi cakupan AngularJS. Akan penutup ini =, <, @, &dan ::. Tulisan lengkap dapat ditemukan di sini .


=membangun ikatan dua arah. Mengubah properti di induk akan menghasilkan perubahan pada anak, dan sebaliknya.


<menetapkan satu cara mengikat, orangtua ke anak. Mengubah properti di induk akan menghasilkan perubahan pada anak, tetapi mengubah properti anak tidak akan mempengaruhi properti induk.


@akan menetapkan pada properti child nilai string dari atribut tag. Jika atribut berisi ekspresi , properti anak diperbarui setiap kali ekspresi mengevaluasi ke string yang berbeda. Sebagai contoh:

<child-component description="The movie title is {{$ctrl.movie.title}}" />
bindings: {
    description: '@', 
}

Di sini, descriptionproperti dalam lingkup anak akan menjadi nilai ekspresi saat ini "The movie title is {{$ctrl.movie.title}}", di mana movieobjek dalam lingkup induk.


&agak sulit, dan pada kenyataannya sepertinya tidak ada alasan kuat untuk menggunakannya. Ini memungkinkan Anda untuk mengevaluasi ekspresi dalam lingkup induk, menggantikan parameter dengan variabel dari lingkup anak. Contoh ( plunk ):

<child-component 
  foo = "myVar + $ctrl.parentVar + myOtherVar"
</child-component>
angular.module('heroApp').component('childComponent', {
  template: "<div>{{  $ctrl.parentFoo({myVar:5, myOtherVar:'xyz'})  }}</div>",
  bindings: {
    parentFoo: '&foo'
  }
});

Diberikan parentVar=10, ekspresi parentFoo({myVar:5, myOtherVar:'xyz'})akan dievaluasi 5 + 10 + 'xyz'dan komponen akan dirender sebagai:

<div>15xyz</div>

Kapan Anda ingin menggunakan fungsi berbelit-belit ini? &sering digunakan oleh orang untuk meneruskan ke fungsi child callback dalam lingkup orang tua. Namun pada kenyataannya, efek yang sama dapat dicapai dengan menggunakan '<' untuk melewati fungsi, yang lebih mudah dan menghindari sintaks kurung kurawal untuk melewati parameter ( {myVar:5, myOtherVar:'xyz'}). Mempertimbangkan:

Panggilan balik menggunakan &:

<child-component parent-foo="$ctrl.foo(bar)"/>
angular.module('heroApp').component('childComponent', {
  template: '<button ng-click="$ctrl.parentFoo({bar:'xyz'})">Call foo in parent</button>',
  bindings: {
    parentFoo: '&'
  }
});

Panggilan balik menggunakan <:

<child-component parent-foo="$ctrl.foo"/>
angular.module('heroApp').component('childComponent', {
  template: '<button ng-click="$ctrl.parentFoo('xyz')">Call foo in parent</button>',
  bindings: {
    parentFoo: '<'
  }
});

Perhatikan bahwa objek (dan array) dilewatkan dengan merujuk ke lingkup anak, tidak disalin. Apa artinya ini adalah bahwa bahkan jika itu adalah pengikatan satu arah, Anda bekerja dengan objek yang sama baik dalam lingkup orangtua dan anak.


Untuk melihat berbagai awalan yang sedang beraksi, buka plunk ini .

Mengikat satu kali (inisialisasi) menggunakan ::

[Dokumen resmi]
Versi AngularJS yang lebih baru memperkenalkan opsi untuk memiliki pengikatan satu kali, di mana properti lingkup anak diperbarui hanya sekali. Ini meningkatkan kinerja dengan menghilangkan kebutuhan untuk menonton properti induk. Sintaksnya berbeda dari di atas; untuk mendeklarasikan pengikatan satu kali, Anda menambahkan ::di depan ekspresi dalam tag komponen :

<child-component 
  tagline = "::$ctrl.tagline">
</child-component>

Ini akan menyebarkan nilai taglinelingkup anak tanpa membangun ikatan satu arah atau dua arah. Catatan : jika taglineawalnya undefineddalam lingkup induk, sudut akan menontonnya sampai itu berubah dan kemudian membuat pembaruan satu kali dari properti yang sesuai dalam lingkup anak.

Ringkasan

Tabel di bawah ini menunjukkan cara awalan bekerja tergantung pada apakah properti adalah objek, array, string, dll.

Bagaimana berbagai ikatan lingkup isolasi bekerja

Mihail Kostira
sumber
4

Properti @ local scope digunakan untuk mengakses nilai string yang ditentukan di luar arahan.

= Dalam kasus di mana Anda perlu membuat ikatan dua arah antara lingkup luar dan ruang lingkup direktif direktif Anda dapat menggunakan karakter =.

& Properti lingkup lokal memungkinkan konsumen dari arahan untuk lulus dalam fungsi yang direktif dapat memohon.

Silakan periksa tautan di bawah ini yang memberi Anda pemahaman yang jelas dengan contoh-contoh. Saya merasa sangat berguna sehingga saya berpikir untuk membagikannya.

http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-2-isolate-scope

Raphael
sumber
3

Bahkan ketika cakupan lokal, seperti dalam contoh Anda, Anda dapat mengakses lingkup induk melalui properti $parent. Asumsikan dalam kode di bawah ini, yang titledidefinisikan pada lingkup induk. Anda kemudian dapat mengakses judul sebagai $parent.title:

link : function(scope) { console.log(scope.$parent.title) },
template : "the parent has the title {{$parent.title}}"

Namun dalam kebanyakan kasus, efek yang sama lebih baik diperoleh dengan menggunakan atribut.

Contoh di mana saya menemukan notasi "&", yang digunakan "untuk meneruskan data dari lingkup terisolasi melalui ekspresi dan ke lingkup induk", berguna (dan penyatuan data dua arah tidak dapat digunakan) berada dalam arahan untuk merender struktur data khusus di dalam pengulangan-ng.

<render data = "record" deleteFunction = "dataList.splice($index,1)" ng-repeat = "record in dataList" > </render>

Salah satu bagian dari rendering adalah tombol delete dan di sini berguna untuk melampirkan penghapusan dari lingkup luar via &. Di dalam render-directive sepertinya

scope : { data = "=", deleteFunction = "&"},
template : "... <button ng-click = "deleteFunction()"></button>"

Penyatuan data 2 arah yaitu data = "="tidak dapat digunakan karena fungsi hapus akan berjalan pada setiap $digestsiklus, yang tidak baik, karena catatan tersebut kemudian segera dihapus dan tidak pernah dirender.

pengguna3750988
sumber
3

perbedaan utama di antara mereka adalah adil

@ Attribute string binding
= Two-way model binding
& Callback method binding
Ashish Kamble
sumber
1

@dan =lihat jawaban lain.

Satu mengerti tentang TL; DR; mendapat ekspresi (tidak hanya berfungsi seperti dalam contoh di jawaban lain) dari orangtua, dan menetapkannya sebagai fungsi dalam direktif, yang memanggil ekspresi. Dan fungsi ini memiliki kemampuan untuk mengganti variabel apa pun (bahkan nama fungsi) dari ekspresi, dengan melewatkan objek dengan variabel. &

&

menjelaskan
& merupakan referensi ekspresi, yang berarti jika Anda lulus sesuatu seperti <myDirective expr="x==y"></myDirective>
dalam direktif ini exprakan menjadi fungsi, yang memanggil ekspresi, seperti:
function expr(){return x == y}.
jadi dalam direktif html <button ng-click="expr()"></button>akan memanggil ekspresi. Dalam arahan direktif hanya $scope.expr()akan memanggil ekspresi juga.
Ekspresi akan dipanggil dengan $ scope.x dan $ scope.y dari induknya.
Anda memiliki kemampuan untuk mengganti parameter!
Jika Anda mengaturnya melalui panggilan, mis. <button ng-click="expr({x:5})"></button>
Maka ekspresi akan dipanggil dengan parameter Anda xdan parameter orang tua y.
Anda dapat mengganti keduanya.
Sekarang Anda tahu, mengapa ) dan mengganti nilai yang mungkin dengan parameter yang Anda tentukan, dalam hal ini .<button ng-click="functionFromParent({x:5})"></button> berhasil.
Karena itu hanya memanggil ekspresi orang tua (mis<myDirective functionFromParent="function1(x)"></myDirective>x
itu bisa:
<myDirective functionFromParent="function1(x) + 5"></myDirective>
atau
<myDirective functionFromParent="function1(x) + z"></myDirective>
dengan panggilan anak: atau bahkan dengan penggantian fungsi:
<button ng-click="functionFromParent({x:5, z: 4})"></button> . .

<button ng-click="functionFromParent({function1: myfn, x:5, z: 4})"></button>

itu hanya sebuah ekspresi, tidak masalah apakah itu suatu fungsi, atau banyak fungsi, atau hanya perbandingan. Dan Anda dapat mengganti variabel apa pun dari ekspresi ini.

Contoh:
template direktif vs kode yang dipanggil:
parent telah mendefinisikan $ scope.x, $ scope.y:
template induk: <myDirective expr="x==y"></myDirective>
<button ng-click="expr()"></button>panggilan $scope.x==$scope.y
<button ng-click="expr({x: 5})"></button>panggilan 5 == $scope.y
<button ng-click="expr({x:5, y:6})"></button>panggilan5 == 6

parent telah mendefinisikan $ scope.function1, $ scope.x, $ scope.y:
templat induk:<myDirective expr="function1(x) + y"></myDirective>

<button ng-click="expr()"></button>Panggilan $scope.function1($scope.x) + $scope.y
<button ng-click="expr({x: 5})"></button>Panggilan $scope.function1(5) + $scope.y
<button ng-click="expr({x:5, y:6})"></button>Panggilan $scope.function1(5) + 6
memiliki $ scope.myFn sebagai fungsi:
<button ng-click="expr({function1: myFn, x:5, y:6})"></button> panggilan$scope.myFn(5) + 6

ya_dimon
sumber
0

Mengapa saya harus menggunakan "{{title}}" dengan '@' dan "title" dengan '='?

Saat Anda menggunakan {{title}}, hanya nilai lingkup induk yang akan diteruskan ke tampilan arahan dan dievaluasi. Ini terbatas pada satu cara, artinya perubahan tidak akan tercermin dalam cakupan induk. Anda dapat menggunakan '=' ketika Anda ingin mencerminkan perubahan yang dilakukan dalam direktif anak ke lingkup orangtua juga. Ini dua arah.

Bisakah saya juga mengakses ruang lingkup induk secara langsung, tanpa mendekorasi elemen saya dengan atribut?

Ketika direktif memiliki atribut scope di dalamnya (scope: {}), maka Anda tidak akan lagi dapat mengakses scope parent secara langsung. Tetapi masih dimungkinkan untuk mengaksesnya melalui lingkup. $ Induk dll. Jika Anda menghapus ruang lingkup dari direktif, itu dapat diakses secara langsung.

Dokumentasi mengatakan "Seringkali diinginkan untuk meneruskan data dari ruang lingkup terisolasi melalui ekspresi dan ke ruang lingkup induk", tetapi itu tampaknya berfungsi dengan baik dengan pengikatan dua arah juga. Mengapa rute ekspresi lebih baik?

Itu tergantung pada konteksnya. Jika Anda ingin memanggil ekspresi atau fungsi dengan data, Anda menggunakan & dan jika Anda ingin berbagi data, Anda dapat menggunakan cara biderectional menggunakan '='

Anda dapat menemukan perbedaan antara beberapa cara mengirimkan data ke arahan di tautan di bawah ini:

AngularJS - Lingkup Terisolasi - @ vs = vs &

http://www.codeforeach.com/angularjs/angularjs-isolated-scopes-vs-vs

Prashanth
sumber
0

@ Atribut string binding (one way) = Penjilidan model dua arah & metode Callback binding

Jatin Patel
sumber
0

@ mengikat properti lingkup direktif lokal / ke nilai yang dievaluasi dari atribut DOM. = mengikat properti lingkup lokal / direktif ke properti lingkup induk. & binding adalah untuk meneruskan metode ke dalam lingkup direktif Anda sehingga dapat dipanggil dalam arahan Anda.

@ Atribut string binding = Pengikatan model dua arah & pengikatan metode Callback

Ashish Kamble
sumber