Estoy buscando algunas pautas que uno pueda usar para ayudar a determinar qué tipo de alcance usar al escribir una nueva directiva. Idealmente, me gustaría algo similar a un diagrama de flujo que me guíe a través de un montón de preguntas y muestre la respuesta correcta: no hay un nuevo alcance nuevo, un nuevo alcance secundario o un nuevo alcance aislado, pero es probable que eso sea pedir demasiado. Aquí está mi conjunto actual de pautas insignificantes:
- No utilice un ámbito aislado si el elemento que va a utilizar los usos directiva NG-modelo
Ver uso Puedo ng-modelo con alcance aislado? y
¿Por qué los formateadores no funcionan con un alcance aislado? - Si la directiva no modifica ninguna propiedad de alcance / modelo, no cree un nuevo alcance
- Los ámbitos de aislamiento parecen funcionar bien si la directiva encapsula un conjunto de elementos DOM ( la documentación dice "una estructura DOM compleja") y la directiva se utilizará como un elemento, o sin otras directivas sobre el mismo elemento.
Soy consciente de que el uso de una directiva con un alcance aislado en un elemento obliga a todas las demás directivas en ese mismo elemento a usar el mismo (un) alcance aislado, entonces, ¿no limita esto severamente cuando se puede usar un alcance aislado?
Espero que algunos del equipo de Angular-UI (u otros que hayan escrito muchas directivas) puedan compartir sus experiencias.
No agregue una respuesta que simplemente diga "use un alcance aislado para componentes reutilizables".
fuente
scope: true
creará un ámbito secundario utilizando$scope.new()
automáticamente.scope: false
(el valor predeterminado, sin nuevo alcance),scope: true
(nuevo alcance que hereda prototípicamente) yscope: { ... }
(nuevo alcance aislado).Respuestas:
¡Qué gran pregunta! Me encantaría escuchar lo que otros tienen que decir, pero aquí están las pautas que uso.
La premisa de gran altitud: el alcance se usa como el "pegamento" que usamos para comunicarnos entre el controlador principal, la directiva y la plantilla de la directiva.
Alcance principal:
scope: false
por lo tanto, no hay ningún alcance nuevoNo uso esto muy a menudo, pero como dijo @MarkRajcok, si la directiva no accede a ninguna variable de alcance (¡y obviamente no establece ninguna!), Entonces esto está bien en lo que a mí respecta. Esto también es útil para las directivas secundarias que solo se usan en el contexto de la directiva principal (aunque siempre hay excepciones a esto) y que no tienen una plantilla. Básicamente, cualquier cosa con una plantilla no pertenece compartiendo un alcance, porque expones inherentemente ese alcance para acceso y manipulación (pero estoy seguro de que hay excepciones a esta regla).
Como ejemplo, recientemente creé una directiva que dibuja un gráfico vectorial (estático) usando una biblioteca SVG que estoy en proceso de escribir. Tiene
$observe
dos atributos (width
yheight
) y los usa en sus cálculos, pero no establece ni lee ninguna variable de alcance y no tiene plantilla. Este es un buen caso de uso para no crear otro ámbito; no necesitamos uno, entonces ¿por qué molestarse?Pero en otra directiva SVG, sin embargo, requería un conjunto de datos para usar y además tenía que almacenar un poco de estado. En este caso, usar el ámbito primario sería irresponsable (nuevamente, en términos generales). Así que en vez...
Alcance del niño:
scope: true
Las directivas con un ámbito secundario tienen en cuenta el contexto y están destinadas a interactuar con el ámbito actual.
Obviamente, una ventaja clave de esto sobre un alcance aislado es que el usuario es libre de usar la interpolación en cualquier atributo que desee; por ejemplo, el uso
class="item-type-{{item.type}}"
de una directiva con un ámbito aislado no funcionará de forma predeterminada, pero funciona bien en uno con un ámbito secundario porque lo que sea que se interpola puede encontrarse de forma predeterminada en el ámbito primario. Además, la propia directiva puede evaluar con seguridad los atributos y expresiones en el contexto de su propio alcance sin preocuparse por la contaminación o el daño a los padres.Por ejemplo, una información sobre herramientas es algo que simplemente se agrega; un alcance aislado no funcionaría (por defecto, ver más abajo) porque se espera que usemos otras directivas o atributos interpolados aquí. La información sobre herramientas es solo una mejora. Pero la información sobre herramientas también necesita establecer algunas cosas en el alcance para usar con una sub-directiva y / o plantilla y obviamente para administrar su propio estado, por lo que sería bastante malo usar el alcance principal. Lo estamos contaminando o dañándolo, y ninguno de los dos es bueno.
Me encuentro usando ámbitos secundarios con más frecuencia que los ámbitos aislados o primarios.
Alcance de aislamiento:
scope: {}
Esto es para componentes reutilizables. :-)
Pero en serio, pienso en los "componentes reutilizables" como "componentes autónomos". La intención es que se usen para un propósito específico, por lo que combinarlos con otras directivas o agregar otros atributos interpolados al nodo DOM inherentemente no tiene sentido.
Para ser más específicos, todo lo necesario para esta funcionalidad independiente se proporciona a través de atributos específicos evaluados en el contexto del ámbito principal; son cadenas unidireccionales ('@'), expresiones unidireccionales ('&') o enlaces de variables bidireccionales ('=').
En componentes autocontenidos, no tiene sentido aplicar otras directivas o atributos porque existe por sí mismo. Su estilo se rige por su propia plantilla (si es necesario) y puede tener el contenido apropiado translúcido (si es necesario). Es independiente, por lo que lo ponemos en un ámbito aislado también para decir: "No te metas con esto. Te estoy dando una API definida a través de estos pocos atributos".
Una buena práctica es excluir la mayor cantidad posible de elementos basados en plantillas del enlace directivo y las funciones del controlador. Esto proporciona otro punto de configuración "similar a la API": ¡el usuario de la directiva puede simplemente reemplazar la plantilla! La funcionalidad permaneció igual, y su API interna nunca se tocó, pero podemos meternos con el estilo y la implementación DOM tanto como sea necesario. ui / bootstrap es un gran ejemplo de cómo hacerlo bien porque Peter y Pawel son increíbles.
Los ámbitos de aislamiento también son excelentes para usar con transclusión. Tomar pestañas; no son solo la funcionalidad completa, sino que lo que sea que esté dentro de él se puede evaluar libremente desde el ámbito principal, dejando las pestañas (y paneles) para hacer lo que quieran. Las pestañas claramente tienen su propio estado , que pertenece al alcance (para interactuar con la plantilla), pero ese estado no tiene nada que ver con el contexto en el que se utilizó: es completamente interno a lo que hace que una directiva de pestañas sea una directiva de pestañas. Además, no tiene mucho sentido usar otras directivas con las pestañas. Son pestañas, ¡y ya tenemos esa funcionalidad!
Rodéelo con más funcionalidad o transcluya más funcionalidad, pero la directiva es lo que ya es.
Dicho todo esto, debo tener en cuenta que existen algunas formas de evitar algunas de las limitaciones (es decir, las características) de un ámbito de aislamiento, como insinuó @ProLoser en su respuesta. Por ejemplo, en la sección de alcance secundario, mencioné la interpolación en la ruptura de atributos no directivos cuando se usa un alcance de aislamiento (por defecto). Pero el usuario podría, por ejemplo, simplemente usar
class="item-type-{{$parent.item.type}}"
y volvería a funcionar. Entonces, si hay una razón convincente para usar un alcance aislado sobre un alcance secundario pero le preocupan algunas de estas limitaciones, sepa que puede solucionarlas prácticamente todas si lo necesita.Resumen
Las directivas sin alcance nuevo son de solo lectura; son completamente confiables (es decir, internos de la aplicación) y no tocan el conector. Las directivas con un ámbito secundario agregan funcionalidad, pero no son la única funcionalidad. Por último, los ámbitos de aislamiento son para directivas que son el objetivo completo; son independientes, por lo que está bien (y la mayoría es "correcto") dejar que se vuelvan rebeldes.
Quería expresar mis pensamientos iniciales, pero a medida que pienso en más cosas, actualizaré esto. Pero mierda, esto es largo para una respuesta TAN ...
PD: Totalmente tangencial, pero como estamos hablando de ámbitos, prefiero decir "prototípico", mientras que otros prefieren "prototípico", que parece ser más preciso, pero no sale del todo bien. :-)
fuente
ngInclude
. O hazlo como parte de tu construcción. ¡Muchas opciones!Mi política personal y experiencia:
Aislado: un cajón de arena privado
Quiero crear una gran cantidad de métodos y variables de alcance que SOLO use mi directiva y que el usuario nunca vea o acceda directamente. Quiero incluir en la lista blanca qué datos de alcance están disponibles para mí. Puedo usar la transclusión para permitir que el usuario regrese al ámbito primario (no afectado) . Yo no quiero que mis variables y métodos accesibles en niños transcluídas.
Niño: una subsección de contenido
Quiero crear métodos y variables de alcance a los que PUEDE acceder el usuario, pero que no son relevantes para los ámbitos circundantes (hermanos y padres) fuera del contexto de mi directiva. También me gustaría permitir que TODOS los datos del ámbito primario se filtren de manera transparente.
Ninguna: directivas simples de solo lectura
Realmente no necesito meterme con métodos o variables de alcance. Probablemente estoy haciendo algo que no tiene que ver con ámbitos (como mostrar complementos jQuery simples, validación, etc.).
Notas
ng-model=$parent.myVal
(niño) ongModel: '='
(aislado).require: '^ngModel'
para buscar en los elementos principales.fuente
Después de escribir muchas directivas, he decidido usar menos
isolated
alcance. Aunque es genial y encapsula los datos y se asegura de no filtrar datos al ámbito principal, limita severamente la cantidad de directivas que pueden usar juntas. Entonces,Si la directiva que va a escribir va a comportarse completamente por sí sola y no la va a compartir con otras directivas, busque un alcance aislado . (como un componente, simplemente puede enchufarlo, sin mucha personalización para el desarrollador final) (se vuelve más complicado cuando intenta escribir subelementos que tienen directivas dentro)
Si la directiva que va a escribir va a acaba de realizar manipulaciones de DOM que se necesita ningún estado interno del ámbito o alcance alteraciones explícitas (en su mayoría cosas muy simples); ir a ningún nuevo ámbito . (tales como
ngShow
,ngMouseHover
,ngClick
,ngRepeat
)Si la directiva que va a escribir necesita cambiar algunos elementos en el ámbito primario, pero también necesita manejar algún estado interno, busque un nuevo ámbito secundario . (como
ngController
)Asegúrese de consultar el código fuente de las directivas: https://github.com/angular/angular.js/tree/master/src/ng/directive
Es de gran ayuda saber cómo pensar en ellas.
fuente
require
, por lo que mantener sus directivas aún desacopladas. Entonces, ¿cómo limita las posibilidades? Incluso hace que las directivas sean más específicas (así que declara de qué dependes). Entonces, dejaría solo una regla: si su directiva tiene estado o necesita algunos datos del alcance donde se usa, use un alcance aislado. De lo contrario, no use el alcance. Y sobre los "ámbitos secundarios": también he escrito muchas directivas y nunca he necesitado esta función. Si "necesita cambiar algunos elementos en el ámbito primario", utilice enlaces.$parent
truco sucio ). Entonces, en realidad, los "ámbitos secundarios" para las directivas es algo que parece que debería usarse bastante atrás, comongRepeat
que crea nuevos ámbitos secundarios para que cada elemento se repita (pero también lo crea usandoscope.$new();
y noscope: true
.ngClick
etc.). Requerir crea una especie de desacoplamiento. Estoy de acuerdo, pero aún debe conocer la directiva principal. A menos que sea como un componente , estoy en contra del aislamiento. Las directivas (al menos, la mayoría de ellas) están destinadas a ser altamente reutilizables y el aislamiento rompe esto.Solo pensé que agregaría mi comprensión actual y cómo se relaciona con otros conceptos de JS.
Predeterminado (por ejemplo, no declarado o alcance: falso)
Esto es filosóficamente equivalente al uso de variables globales. Su directiva puede acceder a todo en el controlador principal, pero también los afecta y se ve afectado al mismo tiempo.
alcance:{}
Esto es como un módulo, cualquier cosa que quiera usar debe pasarse explícitamente. Si CADA directiva que usa es un ámbito aislado, puede ser el equivalente a hacer que CADA archivo JS escriba su propio módulo con mucha sobrecarga al inyectar todas las dependencias.
alcance: niño
Este es el punto medio entre las variables globales y el paso explícito. Es similar a la cadena de prototipos de javascript y solo le extiende una copia del alcance principal. Si crea un ámbito aislado y pasa todos los atributos y funciones del ámbito primario, es funcionalmente equivalente a esto.
La clave es que CUALQUIER directiva se puede escribir de CUALQUIER manera. Las diferentes declaraciones de alcance están ahí para ayudarlo a organizarse. Puede hacer de todo un módulo, o simplemente puede usar todas las variables globales y tener mucho cuidado. Para facilitar el mantenimiento, es preferible modularizar su lógica en partes lógicamente coherentes. Hay un equilibrio entre una pradera abierta y una cárcel cerrada. Creo que la razón por la que esto es complicado es que cuando las personas se enteran de esto, piensan que están aprendiendo sobre cómo funcionan las directivas, pero en realidad están aprendiendo sobre la organización del código / lógica.
Otra cosa que me ayudó a entender cómo funcionan las directivas es aprender sobre ngInclude. ngInclude te ayuda a incluir parciales html. Cuando comencé a usar directivas, descubrí que podía usar su opción de plantilla para reducir su código, pero realmente no estaba adjuntando ninguna lógica.
Por supuesto, entre las directivas de angular y el trabajo del equipo de angular-ui , todavía no he tenido que crear mi propia directiva que haga algo sustancial, por lo que mi punto de vista sobre esto puede ser completamente erróneo.
fuente
Estoy de acuerdo con Umur. En teoría, los ámbitos aislados suenan maravillosos y "portátiles", pero al crear mi aplicación para involucrar una funcionalidad no trivial, me encontré con la necesidad de incorporar varias directivas (algunas anidadas dentro de otras o agregarles atributos) para poder escribir completamente en mi HTML propio, que es el propósito de un lenguaje específico de dominio.
Al final, es demasiado extraño tener que pasar todos los valores globales o compartidos en la cadena con múltiples atributos en cada invocación DOM de una directiva (como se requiere con el alcance aislado). Simplemente parece tonto escribir repetidamente todo eso en el DOM y se siente ineficiente, incluso si se trata de objetos compartidos. También complica innecesariamente las declaraciones de directivas. La solución alternativa del uso de $ parent para "alcanzar" y tomar valores de la directiva HTML parece muy mala.
Yo también terminé cambiando mi aplicación para tener principalmente directivas de alcance infantil con muy pocos aislamientos, solo aquellos que no necesitan acceder a CUALQUIER COSA de los padres que no sea lo que pueden pasar a través de atributos simples y no repetitivos.
Habiendo soñado el sueño de los lenguajes específicos de dominio durante décadas antes de que ocurriera tal cosa, estoy eufórico de que AngularJS brinde esta opción y sé que, a medida que más desarrolladores trabajen en esta área, veremos algunas aplicaciones muy interesantes que También es fácil para sus arquitectos escribir, expandir y depurar.
- D
fuente