Mylić o AngularJS transcluded i izolować lunety i wiązania

[13]}staram się zrozumieć zakres modeli i ich powiązania w odniesieniu do dyrektyw, które mają ograniczony zakres.

Rozumiem, że ograniczenie zakresu dyrektywy oznacza, że kontroler.$ scope and directive.scope to już nie to samo. Jestem jednak zdezorientowany tym, jak umieszczenie modeli w szablonie dyrektywy lub w html wpływa na powiązanie danych. Czuję, że brakuje mi czegoś bardzo fundamentalnego i aby ruszyć dalej, muszę zrozumieć to.

Weź następujący kod (tutaj: http://jsfiddle.net/2ams6/)

JavaScript

var app = angular.module('app',[]);
app.controller('Ctrl',function($scope){
});
app.directive('testel', function(){
    return {
        restrict: 'E',
        scope: {
            title: '@'
        },
        transclude: true,
        template:   '<div ng-transclude>'+
                    '<h3>Template title: {{title}}</h3>' +
                    '<h3>Template data.title:{{data.title}}</h3>' +
                    '</div>'
    }    
}); 

HTML

<div ng-app='app'>
    <div ng-controller="Ctrl">
        <input ng-model="data.title">
        <testel title="{{data.title}}">
            <h3>Transclude title:{{title}}</span></h3>
            <h3>Transclude data.title:{{data.title}}</h3>
        </testel>
    </div>
</div>

Model aktualizuje tylko {{title}} wewnątrz szablonu i {{data.title}} w transclusion. dlaczego nie {{title}} w transclusion ani {{data.title}} w szablonie?

Przenoszenie wejścia do wewnątrz transclusion tak (tutaj: http://jsfiddle.net/eV8q8/1/):

<div ng-controller="Ctrl">
    <testel title="{{data.title}}">
        <input ng-model="data.title">
         <h3>Transclude title: <span style="color:red">{{title}}</span></h3>

         <h3>Transclude data.title: <span style="color:red">{{data.title}}</span></h3>

    </testel>
</div>

Teraz oznacza tylko transclude {{data:title}} dostaje aktualizacja. dlaczego nie szablon {{title}} lub {{data.title}}, ani nie transclude {{title}}?

I na koniec przesunięcie wejścia do wewnątrz szablonu, w ten sposób (tutaj: http://jsfiddle.net/4ngmf/2/):

template: '<div ng-transclude>' +
            '<input ng-model="data.title" />' +
            '<h3>Template title: {{title}}</h3>' +
            '<h3>Template data.title: {{data.title}}</h3>' +
            '</div>'

Teraz oznacza, że tylko szablon {{data.title}} zostanie zaktualizowany. znowu, dlaczego nie pozostałe 3 wiązania?

Mam nadzieję, że coś jest oczywiste patrząc mi w twarz i brakuje mi tego. Jeśli mnie do tego zmusisz, postawię ci piwo, albo dam ci punkty, albo coś takiego. Wielkie dzięki.

Author: dewd, 2013-05-20

3 answers

Twoje skrzypce tworzą trzy zakresy:

  1. zakres związany z kontrolerem Ctrl, ze względu na ng-controller
  2. dyrektywa transkludowana zakres, ze względu na transclude: true
  3. dyrektywa izoluje zakres, ze względu na scope: { ... }

W fiddle1, przed wpisaniem czegokolwiek w pole tekstowe mamy następujące:

Tutaj wpisz opis obrazka

Zakres 003 to zakres związany z kontrolerem. Ponieważ nie wpisaliśmy jeszcze w pole tekstowe, nie ma właściwości data. W izolowanym zakresie 004 widzimy, że została utworzona właściwość title, ale jest ona pusta. Jest pusty, ponieważ zakres nadrzędny nie posiada jeszcze właściwości data.title.

Po wpisaniu my title W pole tekstowe mamy teraz:

Tutaj wpisz opis obrazka

Kontroler scope 003 ma teraz nową właściwość obiektu data (dlatego jest koloru żółtego), która ma właściwość title ustawioną na my title. Ponieważ właściwość isolate scope title jest jednokierunkową bazą danych do interpolowanej wartości data.title, otrzymuje również wartość my title (wartość jest zabarwiona na Żółto, ponieważ się zmieniła).

Transkludowany zakres prototypowo dziedziczy z zakresu kontrolera, więc wewnątrz transkludowanego HTML, angular może podążać za łańcuchem prototypów i znaleźć $scope.data.title w zakresie nadrzędnym (ale $scope.title tam nie istnieje).

Zakres izolowany ma dostęp tylko do własnych właściwości, stąd tylko do właściwości title.

W fiddle2, przed wpisaniem mamy taki sam obrazek jak w fiddle1.

Po wpisaniu my title:

Tutaj wpisz opis obrazka

Zauważ, gdzie pojawiła się nowa właściwość data.title -- na transkludowanym zakresie. Zakres izolowany nadal szuka data.title w zakresie kontrolera, ale tym razem go tam nie ma, więc jego wartość właściwości title pozostaje pusta.

W fiddle3, przed wpisaniem mamy taki sam obrazek jak w fiddle1.

Po wpisaniu my title:

Tutaj wpisz opis obrazka

Zwróć uwagę, gdzie pojawiła się nowa właściwość data.title -- na izolowanym obszarze. Nikt inny zakresy mają dostęp do zakresu izolowanego, więc łańcuch my title nie pojawi się nigdzie indziej.


Aktualizacja dla Angular v1.2:

Ze zmianąeed299a kątowy teraz czyści punkt transcluzji przed transcludacją, więc części Template title: ... i Template data.title: ... nie pojawią się, chyba że zmodyfikujesz szablon tak, aby ng-transclude był sam w sobie, na przykład: {]}

'<h3>Template title: <span style="color:red">{{title}}</span></h3>' +
'<h3>Template data.title: <span style="color:red">{{data.title}}</span></h3>' +
'<div ng-transclude></div>'

W poniższej aktualizacji dla Angular v1. 3 wprowadzono tę zmianę szablonu.


Aktualizacja dla Kątowa v1.3+:

Od wersji Angular v1. 3, transkludowany zakres jest teraz potomkiem izolowanego zakresu dyrektywy, a nie potomkiem zakresu kontrolera. Więc w fiddle1, zanim cokolwiek napiszemy:

Tutaj wpisz opis obrazka

Zdjęcia w tej aktualizacji są rysowane za pomocą narzędzia Peri$scope, więc zdjęcia są nieco inne. @ wskazuje, że mamy właściwość isolate scope, która używa składni @, a różowe tło oznacza, że narzędzie nie było w stanie aby znaleźć odniesienie przodka dla mapowania (co jest prawdą, ponieważ nie wpisaliśmy jeszcze niczego do pola tekstowego).

Po wpisaniu my title W pole tekstowe mamy teraz:

Tutaj wpisz opis obrazka

Właściwości izolujące, które używają wiązania @ zawsze będą wyświetlać wynik interpolowanego ciągu znaków w zakresie izolowania po symbolu @. Peri$scope była również w stanie znaleźć tę dokładną wartość łańcuchową w zakresie nadrzędnym, więc pokazuje również odniesienie do tej właściwości.

W fiddle 2, przed wpisaniem mamy taki sam obrazek jak w fiddle1.

Po wpisaniu my title:

Tutaj wpisz opis obrazka

Zauważ, gdzie pojawiła się nowa właściwość data.title -- na transkludowanym zakresie. Zakres izolowany nadal szuka data.title w zakresie kontrolera, ale tym razem go tam nie ma, więc jego wartość właściwości title pozostaje pusta.

W fiddle3, przed wpisaniem mamy taki sam obrazek jak w fiddle1.

Po wpisaniu my title:

Tutaj wpisz opis obrazka

Zwróć uwagę, gdzie pojawiła się nowa właściwość data.title -- na izolowanym obszarze. Nawet jeśli transkludowany zakres ma dostęp do izolowanego zakresu poprzez relację $parent, nie będzie tam szukał title ani data.title -- będzie szukał tylko w zakresie kontrolera (tzn. będzie podążał za dziedziczeniem prototypowym), a zakres kontrolera nie ma zdefiniowanych tych właściwości.

 113
Author: Mark Rajcok,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-31 03:34:02

Po przeczytaniu wszystkich przedstawionych odpowiedzi, w tym fantastycznych schematów Marka, to jest moje zrozumienie zakresu i jest dziedziczenie na moje pytanie. Byłbym wdzięczny za komentarze na temat tego, gdzie ten diagram spada, w celu mogę zaktualizować odpowiednio. Mam nadzieję, że po prostu daje inny pogląd na to, co przedstawił Mark:

Dziedziczenie zakresu

 22
Author: dewd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-24 14:10:47

Dobrze zapytany, btw! Mam nadzieję, że moja odpowiedź jest równie wymowna..

Odpowiedź ma związek z tym, jak elementy transkludowane uzyskują swój zakres.

Podsumowując, masz dwa zakresy:

  1. zakres kontrolera, który ma $scope.data.title. (Domyślnie dodany przez twój input element)
  2. zakres dyrektywy, który ma $scope.title.

Po zmianie kontrolera $scope.data.title zmienia się również dyrektywa $scope.title.

Masz też dwie sekcje HTML, transkludowaną i szablon. To, co się dzieje, to fakt, że transkludowany HTML znajduje się w zakresie kontrolera , A szablon HTML znajduje się w zakresie dyrektywy . Tak więc transkludowany HTML nie wie nic o title, a zakres szablonów nie wie nic o data.title

Właśnie do tego była przeznaczona Transclusion - , aby umożliwić potomnym elementom dyrektywy zachowanie ich nadrzędnego zakresu , w tym przypadku zakresu kontrolera. Według projektu, transkludowane elementy nie wiedzą, że ich w dyrektywie, a więc nie mają dostępu do zakresu dyrektywy.

Z drugiej strony Szablony dyrektyw będą miały dostęp tylko do zakresu dyrektywy.

Zmieniłem trochę Twój kod, aby nazwy były bardziej przejrzyste (ta sama funkcjonalność)

Http://jsfiddle.net/yWWVs/2/

 8
Author: Roy Truelove,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-20 16:22:33