La directiva es una forma de enseñar a HTML a jugar algunos trucos nuevos. Durante la compilación DOM, las directivas coinciden con HTML y ejecutan. Esto permite el comportamiento de registro de la directiva o la conversión de estructuras DOM.
Angular viene con un conjunto de directivas incorporadas, que es muy útil para construir una aplicación web. Si continúa expandiéndose, puede definir el lenguaje específico del dominio (DSL) en HTML.
1. Directivas de cotización en HTML
La directiva tiene nombres de estilo de camello, como Ngbind (parece ser inutilizable en las propiedades ~). Sin embargo, la directiva también se puede nombrar con un tipo de fondo de serpiente (caso de serpiente), que debe conectarse a través de: (colon), (menos) o _ (bajo). Como opción opcional, la directiva puede prefijarse con "X-" o "Datos-" para satisfacer las necesidades de verificación HTML. Aquí están los nombres legales de las directivas:
La directiva se puede colocar en nombres de elementos, atributos, clases y comentarios. La siguiente es la forma equivalente de citar a MyDir, la directiva. (Pero muchas directivas se limitan al uso de "propiedades")
<span my-dir = "exp"> </span> <span> </span> <hy-dir> </my-dir> <!-Directiva: My-Dir Exp->
La directiva se puede citar de varias maneras, y las siguientes enumeras n formas equivalentes:
<! DocType html> <html lang = "zh-cn" ng-app> <head> <meta charset = "utf-8"> <title> invoke-directive </title> <style type = "text/css"> .ng-cloak {visualización: ninguno; } </style> </head> <body> <div ng-controller = "myctrl"> hello <input ng-model = "name"/> <hr/> ngbind = "name" Esto no se puede usar ~~ <span ngbind = "name"> </span> <br/> ng: bind = "name" <span ng: bind = "name" </</<br/> ng_bind = "name" <span ng_bind = "name"> </span> <br/> ng-bind = "name" <span ng-bind = "name"> </span> <br/> data-ng-bind = "name" <span data-ng-bind = "name"> </span> <br/> x-ng-bind = "name" <span " x-ng-bind = "name"> </span> <br/> </div> <script src = "../ angular-1.0.1.js" type = "text/javascript"> </script> <script type = "text/javaScript"> function myctrl ($ scope) {$ scope.name = "belleza ~~"; } </script> </body> </html>2. Interpolación de cadena
Durante el proceso de compilación, el compilador coincide con el texto con expresiones integradas en atributos (como {{algo}}) a través del servicio $ interpolato. Estas expresiones se registrarán como relojes y se actualizarán juntas como parte del ciclo de resumen (¿no fue un bucle de resumen antes?). Aquí hay una simple interpolación:
<img src = "img/{{username}}. jpg"/> hola {{nombre de usuario}}!
3. Proceso de compilación y coincidencia de directivas
Tres pasos para "compilar" HTML:
1. Primero, convierta HTML en objetos DOM a través de la API estándar del navegador. Este es un paso muy importante. Porque la plantilla debe ser parsable (cumpliendo con las especificaciones). Esto se puede comparar con la mayoría de los sistemas de plantilla, que generalmente se basan en cadenas, no en elementos DOM.
2. La compilación del DOM se realiza llamando al método $ comple (). Este método atraviesa el DOM y coincide con la Directiva. Si la coincidencia es exitosa, se agregará a la lista de directivas junto con el DOM correspondiente. Mientras se identifiquen todas las directivas asociadas con el DOM especificado, se clasificarán en prioridad y ejecutarán su función compilar () en ese orden. La función de compilación de directivas tiene la oportunidad de modificar la estructura DOM y es responsable de generar el análisis de la función Link (). El método $ compile () devuelve una función de enlace combinada, que es una colección de funciones vinculadas devueltas por la función de compilación de la directiva misma.
3. Conecte la plantilla al alcance a través de la función de enlace devuelta en el paso anterior. Esto a su vez llama a la función de vinculación de la Directiva, lo que les permite registrar a algunos oyentes en el elemento y crear algunos relojes con alcance. El resultado en esto es una unión instantánea bidireccional entre el alcance y el DOM. Cuando cambia el alcance, el DOM obtendrá la respuesta correspondiente.
var $ compile = ...; // inyectado en su código var alcance = ...; var html = '<div ng-bind =' exp '> </div>'; // Paso 1: analizar html en la plantilla var de elemento DOM = angular.element (html); // Paso 2: compilar la plantilla var linkfn = $ compile (plantilla); // Paso 3: Enlace la plantilla compilada con el alcance. linkfn (alcance);
4. Razones detrás de la separación de compilación/enlace
En este momento, puede preguntarse por qué el proceso de compilación se divide en dos pasos: compilar y enlace. Para entender esto, echemos un vistazo a un ejemplo real (repetidor)
Hola {{user}}, tiene estas acciones: <ul> <li ng-depreat = "Action in user.actions"> {{Action.description}} </li> </ul>En pocas palabras, la razón por la que separamos los dos pasos de compilación y enlace es que a veces la estructura DOM correspondiente debe cambiarse después de cambiar el modelo, como los repetidores.
Cuando se compila el ejemplo anterior, el compilador iterará a través de todos los nodos para encontrar la directiva. {{usuario}} es un ejemplo de una directiva de interpolación. Ngrepeat es otra directiva. Pero Ngrepeat tiene una dificultad. Requiere la capacidad de crear rápidamente una nueva LI para cada acción en los usuarios. Esto significa que para satisfacer el propósito de clonar LI e incorporar acciones específicas (aquí se refiere a uno de los valores de las acciones del usuario), necesita mantener una copia limpia del elemento LI, que debe clonarse e insertarse en el elemento UL. Pero clonar el elemento LI no es suficiente. Li también necesita ser compilado para que su directiva ({{Action.Descriptions}}) pueda analizarse en el alcance correcto. El método original generalmente simplemente inserta una copia del elemento LI y luego lo compila. Sin embargo, la compilación de copias de cada elemento LI será más lento, porque el proceso de compilación requiere que atravesemos el árbol del nodo DOM, encontremos directivas y las ejecutemos. Si tenemos una compilación que necesita procesar 100 elementos a través del repetidor, entonces estaremos atrapados con problemas de rendimiento.
La solución al problema es dividir el proceso de compilación en dos pasos. La etapa de compilación reconoce todas las directivas y las clasifica por prioridad, vinculando un alcance específico con una LI específica durante la etapa de enlace.
Ngrepeat compila LIS individual por separado para evitar que el proceso de compilación caiga en elementos de LI. El resultado de la compilación del elemento LI es una función de enlace de directiva que contiene todas las directivas contenidas en el elemento LI, listo para conectarse con la copia del elemento LI específico. En tiempo de ejecución, Ngrepeat monitorea la expresión y se agrega como un elemento a una matriz de copias de elementos LI, creando un nuevo alcance para los elementos LI clonados y llamando a la función de enlace correspondiente a la copia.
Resumir:
1. Función de compilación: las funciones de compilación son relativamente raras en las directivas, porque a la mayoría de las directivas solo les importa trabajar con elementos DOM especificados, en lugar de cambiar las plantillas de los elementos DOM (DOM en sí y su estructura interna). Para optimizar el rendimiento, algunas operaciones que pueden compartirse mediante instancias de directiva se pueden mover a la función de compilación.
2. Función de enlace: muy pocas directivas no tienen función de enlace. La función de enlace permite a la directiva registrar un oyente en la copia especificada de la instancia de elemento DOM, o copiar contenido específico del alcance al DOM.
5. Escribe una directiva (versión simple)
En este ejemplo, crearemos una directiva que muestre la hora actual de acuerdo con el formato de entrada.
<! DocType html> <html lang = "zh-cn" ng-app = "timeFormat"> <head> <meta charset = "utf-8"> <title> Time-format </title> </head> <body> <iv ng-controller = "myctrl" id = "principal"> Format de fecha: <input ng-model = "format" type = "Text"/> <hr/> <!-El siguiente atributo X-Current-Time es probar el nombre legal mencionado anteriormente ~~ Current: Time, Time-Time, Current_Time, Data-Current -_-_-! -> La hora actual es: <span x-current time = "format" id = "myFormat"> </span> <br/> <button ng-click = "remove ()"> eliminar el span </boton> </div> <script src = "../ angular-1.0.1.js" type = "text/javaScript"> </script> <script> type = "text/javaScript"> angular.module ("timeFormat", []) // Registre el método de fábrica de directivas de "CurrentTime" en TimeFormat Application // Como se mencionó anteriormente, la inyección de dependencia se puede escribir directamente en los parámetros de la función, inyectado aquí $ TimeOut y DataFilter .Directive ("TIEMPO Current TIME" (Función de fecha) {// Función de compilar, ¿por qué? ...) Función de retorno (alcance, elemento, attr) {var intervalid; alcance. $ watch (attr.currenttime, function (valor) {scope.format = valor; updateTime ();}); }). Controler ("myctrl", function ($ scope, $ rootscope) {$ scope.format = "m/d/yy h: mm: ss a"; $ scope.remove = function () {var oformat = document.getElementByid ("myFormat"); if (oformat) {angular.element (deormat) .Remove (); ¡El evento de destrucción se puede activar!6. Escriba una directiva (versión detallada)
A continuación se muestra una creación de muestra de una directiva (plantilla de definición de objeto de directiva). Si desea ver la lista detallada, continúe leyendo.
var mymodule = angular.module (...); mymodule.directive ('directiveName', function factory (inyectable) {var directiveSeFinitionEnting = {priority: 0, Template: '<div> </div>', templateUrl: 'directive.html', reemplazar: falso, transclude: falso, restrict: 'a', scope: false, compilio: function compilement (telement, tatement, tattrs, transcluD Pre: Función Prelink (alcance, iElement, IATTRS, Controller) {...}, Post: Function Postlink (Scope, IElement, IATTRS, Controller) {...}}}, enlace: function Postlink (Scope, iElement, IATTRS) {...}};En la mayoría de los escenarios, no necesitamos un control preciso, por lo que la definición anterior puede simplificarse. Definir cada parte de la plantilla se explicará en el siguiente capítulo. En este capítulo, solo nos centramos en los isómeros de este esqueleto que definen la plantilla (isómeros de este esqueleto, no entiendo ... espero con ansias la adición de todos).
El primer paso para simplificar su código es confiar en los valores predeterminados. Por lo tanto, el código anterior se puede simplificar a:
var mymodule = angular.module (...); myModule.Directive ('DirectiveName', Function Factory (inyectable) {var directiveDefinitionOntSeCject = {compile: function compile (telement, tattrs) {return Function postlink (scope, iElement, IATTRS) {...}}}; return DirectiveFinitionObject;});La mayoría de las directivas solo se preocupan por las instancias, no la conversión de plantillas, por lo que pueden simplificarse más (traducido muy duro ... esperando la adición de todos):
var mymodule = angular.module (...); mymodule.directive ('directiveName', function fábrica (inyectable) {return function postlink (scope, iElement, iAttrs) {...}});7. Método de fábrica
El método de fábrica es responsable de crear directivas. Se usa solo una vez, solo cuando el compilador primero coincide con la directiva. Puede hacer algunas operaciones de inicialización aquí. El método de fábrica se ejecuta a través de $ inyector.invoke, lo que le permite cumplir con todas las reglas de declaración de inyección (reglas de anotación de inyección), lo que lo hace inyectable.
8. Definición directiva Descripción del objeto
Los objetos de definición de directiva proporcionan la estructura del compilador. Las propiedades son las siguientes:
1.Name - El nombre del alcance actual. El valor predeterminado se puede usar al registrarse (no se llena).
2. Prioridad: cuando hay múltiples directivas definidas en el mismo elemento DOM, a veces es necesario aclarar su orden de ejecución. Esta propiedad se usa para clasificar antes de la llamada de función de compilación de directivas. Si la prioridad es la misma, la orden de ejecución es incierta (después de los experimentos preliminares, aquellos con mayor prioridad se ejecutan primero, y el mismo nivel es similar a la "ejecución posterior a la" ejecución ". Además, fui un poco descuidado durante la prueba. Al definir la directiva, una directiva con el mismo nombre definido fue definido, pero el resultado de la ejecución se encontró que se encontró tanto compilaciones o vínculos.
3.Terminal (último grupo): si se establece en "verdadero", significa que la prioridad actual se convertirá en la directiva del último grupo de ejecución. Si alguna directiva es la misma que la prioridad actual, aún se ejecutará, pero el orden es incierto (aunque el orden es incierto, es básicamente el mismo que el orden de prioridad. Después de ejecutar la prioridad actual, no se ejecutará nuevamente la menor prioridad).
4.cope - si se establece en:
1). True: se creará un nuevo alcance para esta directiva. Si hay múltiples directivas en el mismo elemento que requieren un nuevo alcance, solo creará un alcance. Las nuevas reglas de alcance no se aplican a la plantilla de raíz, por lo que la plantilla de raíz tiende a obtener un nuevo alcance.
2). {} (Objeto hash) - Se creará un nuevo alcance aislado. La diferencia entre el alcance "aislado" y el alcance general es que no se hereda del alcance principal a través de prototipos. Esto es muy útil para crear componentes reutilizables y puede evitar efectivamente leer o modificar los datos del alcance principal. Este alcance independiente crea un hash de objeto con un conjunto de propiedades de alcance local derivadas del alcance principal. Estas propiedades locales son útiles para los valores de alias para las plantillas -_-!. La definición de los locales es un hash de la propiedad de alcance local a su fuente#&) $ &@#) ($ &@#_):
3). @ O @attr: cree una propiedad de alcance local a la propiedad DOM. Debido a que el valor de la propiedad siempre es tipo de cadena, este valor siempre devuelve una cadena. Si el nombre del atributo no se especifica a través de @ATTR, el nombre local siempre será con el nombre del atributo DOM. Por ejemplo, <widget my-attr = "hola {{name}}">, el alcance del widget se define como: {localName: '@myattr'}. Luego, el nombre local de la propiedad del alcance del widget asignará el valor real convertido por "Hola {{name}}". Después de que cambia el valor del atributo de nombre, el atributo localName del alcance del widget también cambiará en consecuencia (solo unidireccional, diferente del "=" a continuación). El atributo de nombre se lee en el alcance principal (no el alcance del componente)
4). = OR = Expression (tal vez attr aquí) - Establezca una unión bidireccional entre el atributo de alcance local y el atributo de alcance principal. Si no se especifica el nombre ATTR, el nombre local será consistente con el nombre del atributo. Por ejemplo, <widget my-attr = "parentModel">, el alcance definido por widget es: {localmodel: '= myattr'}, luego la propiedad del alcance del widget "localName" mapeará el "parentModel" del alcance principal. Si se producen cambios en ParentModel, LocalModel también cambiará y viceversa. (Bi-Way Binding)
5). & O attr - proporciona una forma de ejecutar una expresión en el contexto del alcance principal. Si no se especifica el nombre ATTR, el nombre local será consistente con el nombre del atributo. Por ejemplo, <widget my-attr = ”count = count + value”>, el alcance del widget se define como: {localfn: 'increment ()'}, luego aislar la propiedad del alcance "localfn" apuntará a una función envuelta con una expresión increment (). En términos generales, queremos pasar datos del alcance del aislado al alcance principal a través de una expresión. Esto se puede hacer pasando un mapa del valor clave de una variable local en la función de envoltura de la expresión. Por ejemplo, si la expresión es incremento (cantidad), entonces podemos llamar a Localfn a través de Localfn ({cantidad: 22}) para especificar el valor de la cantidad (el ejemplo anterior realmente no entiende, ¿y dónde fue?).
5. Controlador - Constructor del controlador. El controlador se inicializará antes del paso previo a la reticulación y permitirá que otras directivas compartan a través del nombre requerido con el nombre especificado (consulte la propiedad Requerir a continuación). Esto permitirá que las directivas se comuniquen entre sí y mejoren el comportamiento mutuo. El controlador inyecta los siguientes objetos locales de forma predeterminada:
1). $ Alcance - Alcance combinado con el elemento actual
2). $ Elemento - Elemento actual
3). $ Attrs: el objeto de atributo del elemento actual
4). $ Transclude: una función de enlace de transposición previa al alcance de transposición actual: función (clonelinkingfn). (Una función de vinculación de transcluido previamente al alcance de la traducción correcta)
6. Requerir: solicite a otro controlador que lo pase a la función de enlace de la Directiva actual. requiere que se pase el nombre de un controlador directo. Si el controlador correspondiente a este nombre no se puede encontrar, se lanzará un error. El nombre se puede prefijarse con lo siguiente:
1).? - No arroje excepciones. Esto hace que esta dependencia sea una opción.
2).^ - Un controlador que permite buscar elementos de los padres
7.restrict: una cadena de un subconjunto de EACM, que limita la Directiva al método de declaración especificado. Si se omite, la directiva solo permitirá declaraciones a través de atributos:
1) E-Nombre del elemento: <My-directive> </directive>
2) .A - Nombre del atributo: <div my -diirective = "exp”> </div>
3). C - Nombre de clase: <div class = "my -directive: exp;"> </div>
4) .m-Comentario: <!-Directiva: expp-directive exp->
8.template: si el reemplazo es verdadero, reemplace el contenido de plantilla con el elemento HTML actual y migre las propiedades y la clase del elemento original juntos; Si es falso, el elemento de plantilla se trata como un elemento infantil del elemento actual. Para obtener más información, consulte el capítulo "Creación de widgets" (donde ... la creación de componentes está disponible ...)
9.templateUrl - es básicamente lo mismo que la plantilla, pero la plantilla se carga a través de la URL especificada. Debido a que la carga de la plantilla es asíncrona, la compilación y la vinculación se detendrán y se ejecutarán después de la carga.
10. Replacia: si se establece en True, la plantilla reemplazará el elemento actual en lugar de agregarse al elemento actual como un elemento infantil. (Nota: Cuando es verdadero, la plantilla debe tener un nodo raíz)
11.Transclude: compile el contenido de un elemento para que pueda ser utilizado por directiva. Requerido (en la plantilla) para ser utilizado (referenciado). La ventaja de la transclusión es que la función de vinculación puede obtener una función de traducción que está previamente unida al alcance actual. En general, cree un widget y cree un alcance de aislado. La traducción no es un niño, sino un hermano del alcance aislado. Esto hará que el widget tenga un estado privado y la transclusión estará vinculada al alcance de los padres (preisolados). (No entiendo el párrafo anterior. Pero en los experimentos reales, si MyDirective se llama a través de <cualquier my-directive> {{name}} </cualquier my-dartective> y el transclude se establece en true o una cadena y la plantilla contiene <alguna vez que la conclusión>, el resultado de la compilación de {{name} se insertará en el contenido de alguna vez. Será un lapso adicional en el algo.
1). True - Convierta el contenido de esta directiva. (En este sentido, es compilar directamente el contenido y moverlo al lugar designado)
2). 'Elemento': convierte todo el elemento, incluidas otras directivas con menor prioridad. (Por ejemplo, después de compilar todo el contenido, se trata como un todo (P envuelto afuera) e se inserta en el lugar especificado)
12.compile - Aquí está la función de compilación, que se explicará en detalle en los siguientes capítulos
13.link: aquí está la función de enlace, que se explicará en detalle en el siguiente capítulo. Esta propiedad solo se usa si la propiedad de compilación no está definida.
9. Compilar función
Compilar de funciones (Telement, Tattrs, Transclude) {…}
La función de compilación se utiliza para manejar la conversión de plantillas DOM. Dado que la mayoría de las directivas no requieren plantillas de conversión, la compilación no se usará con frecuencia. Directiva que requiere la función de compilación, generalmente aquellas que necesitan convertir plantillas DOM (como ngrepeat), o las que necesitan cargar contenido de forma asincrónica (como NGView). La función de compilación tiene los siguientes parámetros:
1.Telement: el elemento de plantilla utiliza el elemento directivo actual. Es seguro hacer una conversión de plantilla bajo el elemento actual o el elemento actual del elemento infantil.
2.TATTRS - Atributos de plantilla - Los atributos estandarizados, declarados en el elemento actual, se pueden compartir entre varias directivas. Para más detalles, consulte el capítulo de atributos
3.Transclude una función de enlace para la conversión: función (alcance, clonelbink).
Nota: Si la plantilla ha sido clonada, la instancia de plantilla y la instancia de enlace no pueden ser el mismo objeto. Para hacer esto, no es seguro hacer otra cosa que no sea la conversión DOM en la función de compilación, que se aplicará a todos los clones. En particular, la operación de registro del oyente de eventos DOM debe realizarse en la función de enlace, no en la función de compilación.
La función de compilar puede tener un valor de retorno, y el tipo puede ser función u objeto.
1. La función de retorno generalmente se usa cuando no se requiere la función de compilación (vacía), que es equivalente a registrar una función de enlace a través del enlace (define directamente los atributos de la plantilla).
2. Devuelve un objeto que contiene propiedades pre y post: nos permite controlar cuando la función de enlace se llama durante la fase de enlace. Para obtener más detalles, consulte los siguientes capítulos sobre funciones previas a la reticulación y posterior a la luz.
10. Función de vinculación
enlace de funciones (alcance, iElement, IATTRS, controlador) {…}
La función de enlace es responsable de registrar el oyente de eventos DOM, y también puede realizar operaciones de actualización DOM. La función de enlace se ejecutará después de completar la operación de clonación de plantilla. La mayor parte de la lógica de la directiva se almacena aquí.
1.Scope - Alcope - se usa para registrar relojes (http://docs.angularjs.org/api/ng.$rootscope.scope#$watch).
2.Eloement - Elemento - Elemento utilizado por directiva. Es seguro operar en elementos infantiles en la función posterior al enlace. Porque los elementos infantiles se han vinculado (¿conectado al modelo?!).
3.iattrs - Instancia de atributo - La lista de atributos del elemento actual estándar. Compartido entre todas las funciones de enlace de directiva.
4.Controller - Instancia del controlador: si uno de los controladores se define en la directiva del elemento actual, puede obtener una instancia del controlador aquí. Este controlador se comparte entre todas las directivas, lo que permite que cada directiva trate el controlador como un canal de comunicación entre ellas.
Función previa al enlace
Ejecutar antes del elemento infantil vinculado. No es seguro hacer la conversión DOM aquí, porque la función de enlace del compilador puede no localizar los elementos correctos al vincular.
Función posterior al enlace
Ejecutar después del elemento infantil vinculado. Es seguro realizar la conversión DOM aquí.
11. Atributos
Objeto de atributo - como argumentos en link () o compilar () - es una forma de acceder a lo siguiente:
1. Nombres de atributos estandarizados: Debido a que la Directiva, como Ngbind, se puede manifestar en muchas formas, como "Ng: Bind", "X-NG-Bind" ... Este objeto de atributo nos permite acceder a los atributos a través de nominal estándar (camel).
2. Comunicación entre directivas: todas las directivas comparten una instancia de objeto de atributo, para que las directivas puedan comunicarse entre directivas a través de objetos de atributos.
3. Interpolación de soporte: el atributo de interpolación se asigna a un objeto de atributo, lo que permite que otras directivas lean el valor interpolado.
4. Observe los atributos interpolados: Observe los cambios en los valores de atributos a través de attr. $ Observar, incluida la interpolación (por ejemplo, src = "{{bar}}"). No solo es muy efectivo, sino que también es la única forma de simplemente obtener el valor real. Porque durante la etapa de enlace, la interpolación no se ha asignado (reemplazado por el valor real), por lo que al acceder a ella en este momento, el resultado no está definido.
<! DocType html> <html lang = "zh-cn" ng-app = "directiveproperty"> <head> <meta charset = "utf-8"> <title> directive-attribute-test </titter> <style type = "text/css"> .ng-cloak {display: ninemion: ninemion; } </style> </head> <body ng-controller = "myctrl"> <input type = "text" ng-model = "name" value = "myname"/> <p my-attr = "123" directive-p2 attrdd = "{{name}}"> </p> <script src = "../ angular-1.0.1.js" type = "text/javaScript"> </script> <script type = "text/javaScript"> var app = angular.module ("directiveProperty", []); app.controller ("myctrl", function ($ scope) {$ scope.name = "my pequeño dada";}); var directiveP2 = app.directive ("directiveP2", function () {return {link: function postlink (scope, lele, lattr) {console.log ("myattr:" + lattr.myattr); // 123 console.log ("myattr:" + lattr.attrdd); // umbined lattr. $ observe (»att) (oval), functer (oval), functer (oval). Console.log ('ATtrDD ha cambiado el valor a' + valor);12. Comprender la transclusión y el alcance
A menudo necesitamos algunos componentes reutilizables. Aquí hay un pseudocódigo que muestra cómo puede funcionar un componente de diálogo simple.
<Botton ng-click = "show = true"> show </boton> <dialog visible = "show" on-cancel = "show = false" on-ok = "show = false; dosomthing ()"> el cuerpo va aquí: {{username}} es {{title}}. </cialog>Al hacer clic en el botón "Mostrar" abrirá el cuadro de diálogo. El diálogo tiene un título que está vinculado al "nombre de usuario" de datos, y también hay un párrafo que queremos colocar dentro del diálogo.
La siguiente es una definición de plantilla escrita para el diálogo:
<Div ng-show = "show ()"> <h3> {{title}} </h3> <div ng ng-transclude> </div> <div> <botón ng-click = "onok ()"> Guardar cambia </boton> <button ng-click = "onCancel ()"> Cerrar </botón </div> </div>Esto no se convertirá correctamente a menos que hagamos algún tratamiento especial sobre el alcance.
El primer problema que debemos resolver es que la plantilla de diálogo espera que el título se define y esté vinculado al nombre de usuario cuando se inicialice. Además, el botón requiere que aparezcan dos funciones Onok y OnCancel en el alcance. Esto limita la utilidad del widget ...). Para resolver el problema de mapeo, las variables locales esperadas por la plantilla son creadas por los siguientes métodos locales (locales, que se estima que es el alcance en la plantilla de definición de la directiva):
Alcance: {Título: 'Bind', // Configurar el título para aceptar Onok de unión a datos: 'Expression', // Cree una función de delegado ONOK OnCancel: 'Expression', // Cree una función delegada OnCancel Muestre: 'Accesor' // Crear una función Getter/Setter para la visibilidad.}La creación de propiedades locales en el alcance de control trae dos problemas:
1. Aislamiento (¿Aseño de atributo?) - Si el usuario olvida establecer el título del atributo del elemento en la plantilla de control, el título estará vinculado al "título" del atributo del alcance del antepasado (si corresponde). Esto es impredecible e indeseable.
2. Transclusión: el DOM traducido puede ver a los locales (¿alcance aislado?) Del control. Los locales anularán las propiedades que realmente deben estar vinculadas en la transclusión. En nuestro ejemplo, la propiedad del título en el complemento destruye la propiedad del título de la transclusión.
Para resolver este problema de falta de aislamiento de atributos, necesitamos definir un alcance aislado para esta directiva. El alcance aislotado no se hereda del prototipo del alcance infantil (¿por qué es el alcance infantil? ¿No es el alcance de los padres?) Por lo tanto, no necesitamos preocuparnos por los problemas de conflicto de atributos (como el hermano del alcance actual).
Sin embargo, el alcance aislado trae un nuevo problema: si un DOM traducido es un niño del alcance aislado del widget, entonces no podrá unirse a nada. Por lo tanto, el alcance traducido es un alcance infantil del alcance original creado antes de que el control cree el alcance aislado para la propiedad local. El alcance traducido y aislado pertenece al nodo hermano (en el árbol del alcance).
Esto puede parecer un poco inesperadamente complicado, pero hacerlo trae al menos sorpresas para controlar a los usuarios y a los desarrolladores de control. (El problema se resolvió)
Por lo tanto, la definición de directiva final es aproximadamente la siguiente:
Transclude: True, Scope: {Title: 'Bind', // Configure el título para aceptar la unión de datos ONOK: 'Expression', // Cree una función delegada ONOK OnCancel: 'Expression', // Cree una función Delegate Oncancel Show: 'Accessor' // Cree una función Getter/Setter para la visibilidad. // He intentado esto, pero falló ... por favor continúe leyendo}He intentado reconstruir el código anterior en un ejemplo completo. Si copia directamente, los resultados esperados no se lograrán. Pero después de un poco de modificación, el complemento se puede ejecutar.
<! Doctype html> <html ng-app = "dialog"> <head> <meta http-equiv = "content-type" content = "text/html; charset = utf-8"/> <title> directive-dialog </title> <meta content = "iE = edge, cromno = 1" http-definit. src = "../ angular.js" type = "text/javaScript"> </script> </head> <body> <div ng ng-controller = "myctrl"> <button ng-chick = "show = true"> show </boton> <dialog visible = "{{show}}" en el cancel = "show = false;" on-ok = "show = false; MethodInParentsCope ();"> <!-Los anteriores en cancel y On-ok están referenciados por y en el alcance de aislamiento de la directiva. Si la expresión contiene una función, entonces debe unir la función en el alcance principal (actualmente MyCTRL Scope) -> El cuerpo va aquí: UserName: {{UserName}}, Título: {{Title}}. <ul> <!-También puede jugar así aquí ~ nombres es el alcance principal-> <li ng-depheat = "name in names"> {{name}} </li> </ul> </choiLog> </div> <script type = "text/javaScript"> var myModule = angular.module ("dialog", []); mymodule.controller ("myctrl", function ($ scope) {$ scope.names = ["name1", "name2", "name3"]; $ scope.show = false; $ scope.username = "lclao"; $ scope.title = "título principal"; $ scope.methodinparentscope = function () {alert ("la alerta de la alerta (" lo recuerdo de la alerta en la thing. en el alcance principal !!! ");};}); mymodule.Directive ('dialog', function factory () {return {priority: 100, template: ['<Div ng ng-show = "visible">', '<h3> {{{title}} </h3>', ',' <Div ng-transclude> ng-click="onCancel()">Close</button>', ' </div>', ' </div>', ' </div>'].join(""), replace:false, transclude: true, restrict:'E', scope:{ title:"@",//quote the value of the title attribute of the dialog tag onOk:"&",//reference the content of the on-ok attribute of the dialog tag in La forma de la función de envoltura OnCancel: "&", // usa el formulario de la función de envoltorio referencia al contenido de la propiedad en el cáncer de la etiqueta de diálogo: "@" // se refiere al valor de la propiedad visible de la etiqueta de diálogo}}; </script> </body> </html>13. Creación de componentes
Por lo general, esperamos reemplazar la directiva a través de una estructura DOM compleja (¿el elemento se encuentra? El propósito es probablemente hacer la directiva puntos complejos internos, que parecen puntos increíbles @_ @). Esto hace que la directiva sea un atajo para construir aplicaciones utilizando componentes reutilizables.
Aquí hay un ejemplo de un componente reutilizable:
<! DocType html> <html ng-app = "zippymodule"> <head> <meta http-equiv = "content-type" content = "text/html; charset = utf-8"/> <title> zippymodule </title> <meta content = "ie = borde, crome = 1" htttp-equiv = "x-equiv" x-equiv " <style type = "text/css"> .zippy {border: 1px sólido negro; Pantalla: bloque en línea; Ancho: 250px; } .zippy.opened> .title: antes {content: ''; } .zippy.opened> .body {display: block; } .zippy.closed > .title:before { content: '► '; } .zippy.closed > .body { display: none; } .zippy > .title { background-color: black; color: white; padding: .1em .3em; cursor: puntero; } .zippy > .body { padding: .1em .3em; } </style> <script src="../angular.js" type="text/javascript"></script></head><body> <div ng-controller="MyCtrl"> Title: <input ng-model="title" type="text"><br/> Text: <textarea ng-model="text"></textarea> <hr/> <div zippy-title="Details: {{title}}...">{{text}}</div> </div> <script type="text/javascript"> var myModule = angular.module("ZippyModule", []); myModule.controller("MyCtrl", function ($scope) { $scope.title = "Here is the title"; $scope.text = "Here is the content... "; }); myModule.directive('zippy', function () { return { template: '<div>' + ' <div>{{title}}</div>' +//This title belongs to the property of the current direct isolate scope ' <div ng-transclude></div>' + //What is here, what is obtained is the property of the parent scope '</div>', replace:true, transclude: true, restrict:'C', scope:{ title:"@zippyTitle"//Bind the zippy-title attribute on the directive element}, link:function(scope,element,attrs) { var title = angular.element(element.children()[0]), opened = false; title.bind("click", toogle); element.addClass("closed"); function toogle() { opened = !opened; element.removeClass(opened ? "closed" : "opened"); element.addClass(opened ? "opened" : "closed"); } } }; }); </script></body></html>