personalizadas directivas crear cloak angularjs angularjs-directive angularjs-scope

directivas - Cuando escribo una directiva en AngularJS, ¿cómo decido si no necesito un nuevo alcance, un nuevo alcance secundario o un nuevo alcance aislado?



ng-bind (5)

Mi política personal y experiencia:

Aislado: una caja de arena privada

Quiero crear una gran cantidad de métodos y variables de alcance que SÓLO son utilizados por mi directiva y que nunca son vistos o accedidos directamente por el usuario. Quiero hacer una lista blanca de los datos de alcance disponibles para mí. Puedo usar la transclusión para permitir que el usuario vuelva al ámbito principal (no afectado) . NO quiero que mis variables y métodos sean accesibles en niños transcluidos.

Niño: una subsección de contenido.

Quiero crear métodos y variables de alcance a los que el usuario pueda acceder, pero no son relevantes para los ámbitos (hermanos y padres) circundantes fuera del contexto de mi directiva. También me gustaría dejar que TODOS los datos del ámbito principal se filtren de forma 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 los ámbitos (como mostrar complementos jQuery simples, validación, etc.).

Notas

  • No debe permitir que ngModel u otras cosas afecten directamente su decisión. Puede evitar el comportamiento extraño haciendo cosas como ng-model=$parent.myVal (child) o ngModel: ''='' (isolate).
  • Isolate + Transclude restaurará todo el comportamiento normal de las directivas de hermanos y volverá al ámbito principal, así que tampoco permita que eso afecte su criterio.
  • No juegue con el alcance en ninguno porque es como poner datos en el alcance para la mitad inferior del DOM, pero no la mitad superior, lo que hace que 0 tenga sentido.
  • Preste atención a las prioridades directivas (no tenga ejemplos concretos de cómo esto puede afectar las cosas)
  • Inyecte servicios o use controladores para comunicarse a través de directivas con cualquier tipo de alcance. También puede require: ''^ngModel'' para buscar en los elementos principales.

Estoy buscando algunas pautas que se pueden 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ía a través de un montón de preguntas y saca la respuesta correcta: no hay un nuevo ámbito nuevo, un nuevo ámbito secundario o un nuevo ámbito aislado, pero es probable que eso sea demasiado. Aquí está mi actual conjunto de pautas:

Soy consciente de que usar una directiva con un alcance aislado en un elemento obliga a todas las demás directivas en ese mismo elemento a usar el mismo (uno) alcance aislado, por lo tanto, ¿no limita esto severamente cuando se puede usar un alcance aislado?

Espero que algunos miembros del equipo de Angular-UI (u otros que han escrito muchas directivas) puedan compartir sus experiencias.

No agregue una respuesta que simplemente diga "use un alcance aislado para componentes reutilizables".


¡Qué gran pregunta! Me encantaría escuchar lo que otros tienen que decir, pero aquí están las pautas que utilizo.

La premisa de gran altitud: el alcance se utiliza como el "pegamento" que usamos para comunicarnos entre el controlador principal, la directiva y la plantilla directiva.

Ámbito principal: scope: false , por lo que no hay nuevo ámbito

No uso esto muy a menudo, pero como dijo @MarkRajcok, si la directiva no tiene acceso 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 utilizan en el contexto de la directiva principal (aunque siempre hay excepciones) y que no tienen una plantilla. Básicamente, todo lo que tenga una plantilla no pertenece a compartir un ámbito, porque está exponiendo de manera inherente ese alcance para el acceso y la 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 escribiendo. $observe dos atributos ( width y height ) y los utiliza 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 ¿para qué molestarse?

Pero en otra directiva SVG, sin embargo, requería un conjunto de datos para usar y, además, tuve que almacenar un poco de estado. En este caso, el uso del ámbito principal sería irresponsable (nuevamente, en términos generales). Así que en vez...

Ámbito infantil: scope: true

Las directivas con un ámbito secundario son sensibles al contexto y están destinadas a interactuar con el ámbito actual.

Obviamente, una ventaja clave de esto en un ámbito aislado es que el usuario es libre de usar la interpolación en cualquier atributo que desee; por ejemplo, usar class="item-type-{{item.type}}" en una directiva con un alcance aislado no funcionará por defecto, pero funciona bien en uno con un alcance secundario porque todo lo que esté interpolado todavía puede encontrarse por defecto en el alcance padre. Además, la directiva en sí misma puede evaluar de forma segura los atributos y expresiones en el contexto de su propio alcance sin tener que preocuparse por la contaminación o daños a los padres.

Por ejemplo, una información sobre herramientas es algo que simplemente se agrega; un alcance aislado no funcionaría (de manera predeterminada, ver más abajo) porque se espera que utilicemos otras directivas o atributos interpolados aquí. La información sobre herramientas es solo una mejora. Pero la información sobre herramientas también debe establecer algunas cosas sobre el alcance para usar con una subdirectiva y / o plantilla y, obviamente, para administrar su propio estado, por lo que sería bastante malo utilizar el alcance principal. Lo estamos contaminando o dañando, y tampoco lo 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 autocontenidos". La intención es que se usen para un propósito específico, por lo que combinarlos con otras directivas o agregar inherentemente otros atributos interpolados al nodo DOM no tiene sentido.

Para ser más específico, 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 de una vía (''@''), expresiones de una vía (''&'') o enlaces de variables de dos vías (''='').

En los componentes autocontenidos, no tiene sentido tener que aplicar otras directivas o atributos, ya que existe por sí mismo. Su estilo se rige por su propia plantilla (si es necesario) y puede tener el contenido apropiado transcluido (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 recomendada es excluir la mayor cantidad posible de elementos basados ​​en plantillas del enlace de la directiva y las funciones del controlador. Esto proporciona otro punto de configuración "tipo API": ¡el usuario de la directiva simplemente puede reemplazar la plantilla! La funcionalidad se mantuvo igual, y su API interna nunca se tocó, pero podemos alterar el estilo y la implementación de DOM tanto como sea necesario. ui / bootstrap es un gran ejemplo de cómo hacerlo bien porque Peter y Pawel son increíbles.

Los alcances aislados también son excelentes para usar con la transclusión. Tomar pestañas; no solo son la funcionalidad completa, sino que todo lo que se encuentra dentro de ella 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 ámbito (para interactuar con la plantilla), pero ese estado no tiene nada que ver con el contexto en el que se usó; es totalmente interno a lo que hace que una directiva de pestañas sea una directiva de pestañas. Además, no tiene mucho sentido utilizar otras directivas con las pestañas. Son pestañas, ¡y ya tenemos esa funcionalidad!

Rodéalo con más funcionalidad o transcluye más funcionalidad, pero la directiva ya es lo que es.

Dicho todo esto, debo señalar que hay formas de evitar algunas de las limitaciones (es decir, las características) de un alcance aislado, como @ProLoser insinuó en su respuesta. Por ejemplo, en la sección de ámbito secundario, mencioné la interpolación en la ruptura de atributos no directivos cuando se utiliza un ámbito de aislamiento (de forma predeterminada). Pero el usuario podría, por ejemplo, simplemente usar class="item-type-{{$parent.item.type}}" y una vez más funcionará. Por lo tanto, si existe una razón convincente para usar un alcance aislado en un alcance secundario, pero está preocupado por algunas de estas limitaciones, sepa que puede solucionar prácticamente todas ellas si es necesario.

Resumen

Las directivas sin nuevo alcance 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 aislados son para directivas que constituyen el objetivo completo; son independientes, así que está bien (y lo más "correcto") dejarlos ir sin escrúpulos.

Quería sacar mis pensamientos iniciales, pero a medida que pienso en más cosas, actualizaré esto. Pero mierda santa - esto es mucho para una respuesta de SO ...

PD: Totalmente tangencial, pero ya que 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. :-)


Después de escribir muchas directivas, he decidido usar un alcance menos isolated . A pesar de que es genial y usted encapsula los datos y se asegura de no filtrar datos al ámbito principal, limita severamente la cantidad de directivas que pueden usar juntas. Asi que,

Si la directiva que va a escribir se va a comportar completamente por su cuenta y no la va a compartir con otras directivas, vaya a un alcance aislado . (como un componente en el que puede enchufarlo, sin mucha personalización para el desarrollador final) (se vuelve más complicado cuando intenta escribir subelementos que tienen directivas)

Si la directiva que va a escribir solo va a realizar manipulaciones dom, que no necesita un estado interno de alcance, o alteraciones explícitas del alcance (en su mayoría cosas muy simples); Ir para ningún nuevo ámbito . (como ngShow , ngMouseHover , ngClick , ngRepeat )

Si la directiva que va a escribir necesita cambiar algunos elementos en el ámbito principal, pero también necesita controlar algún estado interno, elija un nuevo ámbito secundario . (como ngController )

Asegúrese de revisar el código fuente de las directivas: https://github.com/angular/angular.js/tree/master/src/ng/directive
Ayuda mucho sobre cómo pensar en ellos.


Estoy de acuerdo con Umur. En teoría, los ámbitos aislados suenan maravillosos y "portátiles", pero al construir mi aplicación para involucrar una funcionalidad no trivial, encontré la necesidad de incorporar varias directivas (algunas anidadas dentro de otras o agregarles atributos) para 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 cada valor global o compartido por la cadena con múltiples atributos en cada invocación de 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 estos son objetos compartidos. También complica innecesariamente las declaraciones directivas. La solución al uso de $ parent para "alcanzar" y capturar valores de la directiva HTML parece muy mala forma.

Yo también terminé cambiando mi aplicación para tener directivas de alcance en su mayoría con muy pocos aislamientos, solo aquellos que no necesitan acceder a NADA del padre, aparte de lo que se puede pasar por atributos simples y no repetitivos.

Habiendo soñado con el sueño de lenguajes específicos de dominio durante décadas antes de que existiera tal cosa, me alegro de que AngularJS proporcione esta opción y sé que, a medida que más desarrolladores trabajan en esta área, vamos a ver algunas aplicaciones muy interesantes que También son fáciles de escribir, expandir y depurar para sus arquitectos.

- D


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 a usar variables globales. Su directiva puede acceder a todo en el controlador principal, pero también les afecta y se ve afectado al mismo tiempo.

alcance:{}

Esto es como un módulo, cualquier cosa que quiera usar debe pasar explícitamente. Si CADA directiva que usa es un ámbito aislado, puede ser el equivalente a hacer que TODO archivo JS escriba su propio módulo con una gran cantidad de 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 ámbito principal. Si crea un ámbito de aislamiento y pasa cada atributo y función del ámbito principal, es funcionalmente equivalente a esto.

La clave es que CUALQUIER directiva puede escribirse de CUALQUIER manera. Las diferentes declaraciones de alcance están ahí para ayudarte a organizar. Puede convertir todo en un módulo, o simplemente puede usar todas las variables globales y ser muy cuidadoso. Por su facilidad de 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 aprenden sobre esto piensan que están aprendiendo cómo funcionan las directivas, pero en realidad están aprendiendo sobre la organización de 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 podría usar su opción de plantilla para reducir su código, pero en realidad 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 opinión sobre esto puede ser completamente errónea.