Szukam wskazówek, które można wykorzystać, aby określić, jakiego rodzaju zakresu należy użyć podczas pisania nowej dyrektywy. Idealnie chciałbym coś podobnego do schematu blokowego, który poprowadzi mnie przez kilka pytań i wyskoczy prawidłową odpowiedź - bez nowego zakresu, nowego zakresu potomnego lub nowego zakresu izolowania - ale to prawdopodobnie wymaga zbyt wiele. Oto mój obecny marny zestaw wskazówek:
- Nie używaj izolowanego zakresu, jeśli element, który będzie korzystał z dyrektywy, używa modelu ng
Zobacz Czy mogę używać modelu ng z izolowanym zakresem? i
dlaczego formaterers nie działa z izolowanym zakresem? - Jeśli dyrektywa nie modyfikuje żadnych właściwości zakresu / modelu, nie twórz nowego zakresu
- Wydaje się, że zakresy izolowania działają dobrze, jeśli dyrektywa hermetyzuje zestaw elementów DOM ( dokumentacja mówi „złożona struktura DOM”), a dyrektywa będzie używana jako element lub bez innych dyrektyw dotyczących tego samego elementu.
Wiem, że użycie dyrektywy z izolowanym zasięgiem na elemencie zmusza wszystkie inne dyrektywy dotyczące tego samego elementu do korzystania z tego samego (jednego) zakresu izolowania, więc czy nie ogranicza to poważnie, kiedy można zastosować zakres izolowania?
Mam nadzieję, że niektórzy z zespołu Angular-UI (lub inni, którzy napisali wiele dyrektyw) mogą podzielić się swoimi doświadczeniami.
Nie dodawaj odpowiedzi, która po prostu mówi „użyj izolowanego zakresu dla komponentów wielokrotnego użytku”.
źródło
scope: true
utworzy zakres potomny przy użyciu$scope.new()
automatycznie.scope: false
(domyślny, brak nowego zakresu),scope: true
(nowy zakres dziedziczy prototypowo) iscope: { ... }
(nowy zakres izolowania).Odpowiedzi:
Cóż za świetne pytanie! Ja uwielbiam słuchać, co inni mają do powiedzenia, ale tutaj są wytyczne używam.
Przesłanka: zakres wysokościowy jest używana jako „klej”, którego używamy do komunikacji między kontrolerem nadrzędnym, dyrektywą i szablonem dyrektywy.
Zakres nadrzędny:
scope: false
więc w ogóle nie ma nowego zakresuNie używam tego zbyt często, ale jak powiedział @MarkRajcok, jeśli dyrektywa nie ma dostępu do żadnych zmiennych zakresu (i oczywiście nie ustawia żadnych!), To jest to dla mnie w porządku. Jest to również pomocne w przypadku dyrektyw podrzędnych, które są używane tylko w kontekście dyrektywy nadrzędnej (choć zawsze są wyjątki od tej zasady) i które nie mają szablonu. Zasadniczo cokolwiek z szablonem nie należy do dzielenia zakresu, ponieważ z natury ujawniasz ten zakres dostępu i manipulacji (ale jestem pewien, że istnieją wyjątki od tej reguły).
Jako przykład niedawno stworzyłem dyrektywę, która rysuje (statyczną) grafikę wektorową przy użyciu biblioteki SVG, którą właśnie piszę. Jest
$observe
to dwa atrybuty (width
iheight
) i wykorzystuje je w swoich obliczeniach, ale nie ustawia ani nie odczytuje żadnych zmiennych zakresu i nie ma szablonu. Jest to dobry przypadek użycia, aby nie tworzyć innego zakresu; nie potrzebujemy jednego, więc po co zawracać sobie głowę?Jednak w innej dyrektywie SVG wymagałem zestawu danych do użycia i dodatkowo musiałem przechowywać odrobinę stanu. W takim przypadku użycie zakresu nadrzędnego byłoby nieodpowiedzialne (ponownie, ogólnie rzecz biorąc). Więc zamiast...
Zakres dziecka:
scope: true
Dyrektywy z zakresem potomnym są kontekstowe i mają na celu interakcję z bieżącym zakresem.
Oczywiście kluczową zaletą tego w stosunku do zakresu izolowanego jest to, że użytkownik może swobodnie korzystać z interpolacji dowolnych atrybutów; np. użycie
class="item-type-{{item.type}}"
dyrektywy z zasięgiem izolowanym nie będzie domyślnie działać, ale działa dobrze na jednym z zasięgiem potomnym, ponieważ wszystko, co jest interpolowane, nadal domyślnie znajduje się w zakresie nadrzędnym. Również sama dyrektywa może bezpiecznie oceniać atrybuty i wyrażenia w kontekście własnego zakresu, nie martwiąc się o zanieczyszczenie lub uszkodzenie rodzica.Na przykład podpowiedź to coś, co dopiero się dodaje; zakres izolowany nie działałby (domyślnie, patrz poniżej), ponieważ oczekuje się, że użyjemy tutaj innych dyrektyw lub interpolowanych atrybutów. Etykietka to tylko ulepszenie. Jednak podpowiedź musi również określać pewne elementy zakresu, aby używać go z pod-dyrektywą i / lub szablonem, i oczywiście zarządzać własnym stanem, więc byłoby naprawdę źle używać zakresu nadrzędnego. Zanieczyszczamy to lub uszkadzamy, i nie bueno.
Często używam lunet dziecięcych niż lunet izolacyjnych lub nadrzędnych.
Wyizoluj zakres:
scope: {}
Dotyczy to komponentów wielokrotnego użytku. :-)
Ale poważnie myślę o „komponentach wielokrotnego użytku” jak o „komponentach samowystarczalnych”. Chodzi o to, aby miały być używane do określonego celu, więc łączenie ich z innymi dyrektywami lub dodawanie innych interpolowanych atrybutów do węzła DOM z natury nie ma sensu.
Mówiąc ściślej, wszystko, co jest potrzebne do tej samodzielnej funkcjonalności, jest dostarczane poprzez określone atrybuty oceniane w kontekście zakresu nadrzędnego; są to albo ciągi jednokierunkowe („@”), wyrażenia jednokierunkowe („&”), albo dwukierunkowe powiązania zmiennych („=”).
W przypadku komponentów niezależnych nie ma sensu stosowanie innych dyrektyw lub atrybutów, ponieważ istnieje ona sama. Jego stylem rządzi własny szablon (w razie potrzeby) i można przenieść odpowiednią treść (w razie potrzeby). Jest samodzielny, więc umieściliśmy go w izolowanym zakresie, aby powiedzieć: „Nie zadzieraj z tym. Daję ci zdefiniowane API poprzez te kilka atrybutów”.
Dobrą najlepszą praktyką jest wykluczenie jak największej liczby elementów opartych na szablonie z funkcji łącza dyrektywy i kontrolera, jak to możliwe. Zapewnia to kolejny punkt konfiguracji „podobny do API”: użytkownik dyrektywy może po prostu zastąpić szablon! Funkcjonalność pozostała taka sama, a jej wewnętrzny interfejs API nigdy nie został zmieniony, ale możemy popsuć stylem i implementacją DOM tyle, ile potrzebujemy. Interfejs użytkownika / bootstrap jest doskonałym przykładem tego, jak to zrobić dobrze, ponieważ Peter i Paweł są niesamowici.
Lunety z izolatami świetnie nadają się również do stosowania z transkluzją. Weź karty; stanowią one nie tylko całą funkcjonalność, ale wszystko, co jest w środku , można swobodnie oceniać z zakresu nadrzędnego, pozostawiając zakładki (i panele), aby zrobić, co chcą. Karty mają oczywiście swój własny stan , który należy do zakresu (do interakcji z szablonem), ale ten stan nie ma nic wspólnego z kontekstem, w którym został użyty - jest całkowicie wewnętrzny z tego, co czyni dyrektywę tabu dyrektywą tab. Ponadto nie ma sensu używać żadnych innych dyrektyw z kartami. To są zakładki - a my już mamy tę funkcjonalność!
Otocz go większą funkcjonalnością lub włącz więcej funkcjonalności, ale dyrektywa jest już taka, jak jest.
To powiedziawszy, należy zauważyć, że istnieją pewne sposoby obejścia niektórych ograniczeń (tj. Cech) izolowanego zakresu, jak wskazał @ProLoser w swojej odpowiedzi. Na przykład w sekcji zakresu potomnego wspomniałem o interpolacji w przypadku łamania atrybutów niebędących dyrektywami podczas korzystania z zakresu izolowanego (domyślnie). Ale użytkownik może na przykład po prostu użyć
class="item-type-{{$parent.item.type}}"
i to po raz kolejny zadziała. Jeśli więc istnieje ważny powód, aby używać lunety izolacyjnej nad lunetą potomną, ale martwisz się niektórymi z tych ograniczeń, wiedz, że możesz obejść je wszystkie, jeśli zajdzie taka potrzeba.Podsumowanie
Dyrektywy bez nowego zakresu są tylko do odczytu; są całkowicie zaufani (tj. wewnętrzni dla aplikacji) i nie dotykają wtyczki jack. Dyrektywy z zakresem potomnym dodają funkcjonalność, ale nie są jedyną funkcjonalnością. Wreszcie, izolowane zakresy dotyczą dyrektyw, które są całym celem; są samodzielne, więc jest w porządku (i większość „poprawnych”), aby pozwolić im przejść na nieuczciwość.
Chciałem poznać moje początkowe przemyślenia, ale kiedy wymyślę więcej rzeczy, zaktualizuję to. Ale cholera - to długo czeka na SO odpowiedź ...
PS: Całkowicie styczna, ale skoro mówimy o zakresach, wolę powiedzieć „prototypowy”, podczas gdy inni wolą „prototypowy”, który wydaje się być bardziej dokładny, ale po prostu nie zsuwa się z języka. :-)
źródło
ngInclude
. Lub zrób to jako część swojej kompilacji. Dużo opcji!Moja osobista polityka i doświadczenie:
Izolowany: prywatny piaskownica
Chcę utworzyć wiele metod zakresu i zmiennych, które są WYŁĄCZNIE używane w mojej dyrektywie i nigdy nie są widoczne ani dostępne dla użytkownika. Chcę dodać do białej listy, jaki zakres danych jest dla mnie dostępny. Mogę użyć opcji integracji, aby umożliwić użytkownikowi powrót do zakresu nadrzędnego (bez zmian) . Ja nie chce moje zmienne i metody dostępne w dołączany dzieci.
Dziecko: podsekcja treści
Chcę utworzyć metody zakres i zmienne, które MOGĄ być dostępne przez użytkownika, ale nie odnoszą się do otaczającego zakresów (rodzeństwo i rodzice) poza kontekstem moim dyrektywy. Chciałbym również pozwolić, aby WSZYSTKIE dane zakresu nadrzędnego przesuwały się w przejrzysty sposób.
Brak: proste dyrektywy tylko do odczytu
Naprawdę nie muszę zadzierać z metodami lub zmiennymi zakresu. Prawdopodobnie robię coś, co nie ma związku z zasięgami (takie jak wyświetlanie prostych wtyczek jQuery, sprawdzanie poprawności itp.).
Notatki
ng-model=$parent.myVal
(dziecko) lubngModel: '='
(izoluj).require: '^ngModel'
zajrzeć do elementów nadrzędnych.źródło
Po napisaniu wielu dyrektyw postanowiłem użyć mniejszego
isolated
zakresu. Mimo że jest to fajne i hermetyzujesz dane i pamiętasz, aby nie przeciekać danych do zakresu nadrzędnego, znacznie ogranicza to liczbę dyrektyw, których możesz używać razem. Więc,Jeśli dyrektywa, którą napiszesz, zachowa się całkowicie sama i nie będziesz dzielić się nią z innymi dyrektywami, wybierz izolowany zakres . (np. komponent, który można po prostu podłączyć, bez zbytniego dostosowywania dla końcowego programisty) (staje się to trudniejsze, gdy próbujesz pisać podelementy, które zawierają dyrektywy)
Jeśli dyrektywa, którą napiszesz, będzie po prostu dokonywała manipulacji domem, które nie wymagają wewnętrznego stanu zakresu, lub wyraźnych zmian zakresu (głównie bardzo prostych rzeczy); iść do żadnego nowego zakresu . (takie jak
ngShow
,ngMouseHover
,ngClick
,ngRepeat
)Jeśli dyrektywa, którą zamierzasz napisać, musi zmienić niektóre elementy w zakresie nadrzędnym, ale musi także obsługiwać stan wewnętrzny, wybierz nowy zakres podrzędny . (takie jak
ngController
)Koniecznie sprawdź kod źródłowy dla dyrektyw: https://github.com/angular/angular.js/tree/master/src/ng/directive
Bardzo pomaga w tym, jak o nich myśleć
źródło
require
, dzięki czemu dyrektywy pozostaną oddzielone. Jak więc ogranicza możliwości? To jeszcze bardziej uszczegóławia dyrektywy (więc zadeklaruj, na czym polegasz). Pozostawiłbym więc tylko jedną zasadę: jeśli twoja dyrektywa ma stan lub potrzebuje danych z zakresu, w którym jest używana - użyj zakresu izolowanego. W przeciwnym razie nie używaj zakresu. I o „dziecięcych zakresach” - napisałem też sporo dyrektyw i nigdy nie potrzebowałem tej funkcji. Jeśli „trzeba zmienić niektóre elementy w zakresie nadrzędnym” - użyj powiązań.$parent
włamania). Więc tak naprawdę „zakresy potomne” dla dyrektyw to coś, co wygląda na to, że powinno być używane całkiem z tyłu - tak,ngRepeat
że tworzy nowe zakresy potomne dla każdego elementu do powtórzenia (ale także tworzy go przy użyciuscope.$new();
i niescope: true
.ngClick
itp.) Wymaganie tworzy rodzaj rozdzielenia Zgadzam się, ale nadal musisz znać dyrektywę nadrzędną. O ile nie jest to element , jestem przeciwny izolacji. Dyrektywy (przynajmniej większość z nich) mają być w wysokim stopniu wielokrotnego użytku, a izolacja to psuje.Pomyślałem, że dodam moje obecne rozumienie i to, jak odnosi się ono do innych koncepcji JS.
Domyślne (np. Niezadeklarowane lub zakres: fałsz)
Jest to filozoficznie równoważne z użyciem zmiennych globalnych. Twoja dyrektywa może uzyskać dostęp do wszystkiego w kontrolerze nadrzędnym, ale wpływa również na nie i jest jednocześnie dotknięta.
zakres:{}
To jest jak moduł, wszystko, czego chce użyć, musi zostać przekazane jawnie. Jeśli KAŻDA dyrektywa, której używasz, jest zakresem izolowanym, może to być odpowiednik tworzenia KAŻDEGO pliku JS, który piszesz swój własny moduł z dużym nakładem pracy przy wprowadzaniu wszystkich zależności.
zakres: dziecko
Jest to środek pomiędzy zmiennymi globalnymi a jawnym przekazywaniem. Jest podobny do łańcucha prototypów javascript i po prostu rozszerza kopię zakresu nadrzędnego. Jeśli utworzysz zakres izolowany i przekażesz każdy atrybut i funkcję zakresu nadrzędnego, będzie to funkcjonalnie równoważne z tym.
Kluczem jest to, że KAŻDĄ dyrektywę można napisać W DOWOLNY sposób. Różne deklaracje zakresu są tylko po to, aby pomóc Ci zorganizować. Możesz uczynić wszystko modułem lub możesz po prostu użyć wszystkich zmiennych globalnych i być bardzo ostrożnym. Jednak dla ułatwienia konserwacji lepiej jest modulować logikę na logicznie spójne części. Istnieje równowaga między otwartą łąką a zamkniętym więzieniem. Uważam, że powodem, dla którego jest to trudne, jest fakt, że kiedy ludzie się o tym dowiadują, myślą, że uczą się, jak działają dyrektywy, ale w rzeczywistości uczą się o organizacji kodu / logiki.
Kolejną rzeczą, która pomogła mi zrozumieć, jak działają dyrektywy, jest poznanie ngInclude. ngInclude pomaga dołączyć częściowe HTML. Kiedy po raz pierwszy zacząłem używać dyrektyw, odkryłem, że możesz użyć opcji szablonu, aby zmniejszyć swój kod, ale tak naprawdę nie przywiązywałem żadnej logiki.
Oczywiście między dyrektywami angular a pracą zespołu angular-ui nie musiałem jeszcze tworzyć własnej dyrektywy, która robi cokolwiek istotnego, więc moje zdanie na ten temat może być całkowicie błędne.
źródło
Zgadzam się z Umurem. Teoretycznie izolowane zakresy brzmią wspaniale i „przenośnie”, ale budując moją aplikację tak, aby obejmowała nietrywialne funkcje, natknąłem się na potrzebę włączenia kilku dyrektyw (niektóre zagnieżdżone w innych lub dodanie do nich atrybutów), aby w pełni napisać w mojej własny HTML, który jest celem języka specyficznego dla domeny.
W końcu jest zbyt dziwne, aby przekazywać każdą globalną lub wspólną wartość w dół łańcucha z wieloma atrybutami przy każdym wywołaniu DOM dyrektywy (zgodnie z wymaganiami w zakresie izolowania). To po prostu głupie, aby powtarzać to wszystko w DOM i wydaje się nieefektywne, nawet jeśli są to wspólne obiekty. Niepotrzebnie komplikuje to również deklaracje dyrektywy. Obejście polegające na używaniu $ parent do „sięgania” i pobierania wartości z HTML-u dyrektywy wydaje się bardzo złym formularzem.
Ja też skończyłem na zmianie mojej aplikacji, aby mieć głównie dyrektywy o zasięgu dziecięcym z bardzo małą liczbą izolatów - tylko te, które nie muszą uzyskiwać dostępu do ŻADNEGO elementu nadrzędnego poza tym, co można przekazać za pomocą prostych, niepowtarzalnych atrybutów.
Przez dziesięciolecia marzyłem o marzeniach związanych z domenami, zanim coś takiego się wydarzyło. Jestem podekscytowany, że AngularJS zapewnia tę opcję i wiem, że w miarę, jak więcej programistów pracuje w tym obszarze, zobaczymy kilka bardzo fajnych aplikacji, które ich architekci mogą również łatwo pisać, rozszerzać i debugować.
- D
źródło