¿Cuál es la diferencia entre ng-if y ng-show / ng-hide

427

Estoy tratando de entender la diferencia entre ng-ify ng-show/ ng-hide, pero me parecen iguales.

¿Hay alguna diferencia que debería tener en cuenta al elegir usar uno u otro?

Stephane Rolland
fuente

Respuestas:

521

ngIf

La ngIfdirectiva elimina o recrea una parte del árbol DOM en función de una expresión. Si la expresión asignada a se ngIfevalúa como un valor falso, el elemento se elimina del DOM; de lo contrario, se vuelve a insertar un clon del elemento en el DOM.

<!-- when $scope.myValue is truthy (element is restored) -->
<div ng-if="1"></div>

<!-- when $scope.myValue is falsy (element is removed) -->
<div ng-if="0"></div>

Cuando se elimina un elemento usando ngIfsu alcance, se destruye y se crea un nuevo alcance cuando se restaura el elemento. El ámbito creado dentro ngIfhereda de su ámbito primario utilizando herencia prototípica.

Si ngModelse usa ngIfpara enlazar a una primitiva JavaScript definida en el ámbito primario, cualquier modificación realizada a la variable dentro del ámbito secundario no afectará el valor en el ámbito primario, por ejemplo

<input type="text" ng-model="data">
<div ng-if="true">
    <input type="text" ng-model="data">
</div>        

Para solucionar esta situación y actualizar el modelo en el ámbito primario desde el ámbito secundario, use un objeto:

<input type="text" ng-model="data.input">
<div ng-if="true">
    <input type="text" ng-model="data.input">
</div>

O, $parentvariable para hacer referencia al objeto de ámbito primario:

<input type="text" ng-model="data">
<div ng-if="true">
    <input type="text" ng-model="$parent.data">
</div>

ngShow

La ngShowdirectiva muestra u oculta el elemento HTML dado en función de la expresión proporcionada al ngShowatributo. El elemento se muestra u oculta eliminando o agregando la ng-hideclase CSS en el elemento. La .ng-hideclase CSS está predefinida en AngularJS y establece el estilo de visualización en ninguno (usando una !importantbandera).

<!-- when $scope.myValue is truthy (element is visible) -->
<div ng-show="1"></div>

<!-- when $scope.myValue is falsy (element is hidden) -->
<div ng-show="0" class="ng-hide"></div>

Cuando la ngShowexpresión se evalúa false, la ng-hideclase CSS se agrega al classatributo en el elemento, lo que hace que se oculte. Cuando true, la ng-hideclase CSS se elimina del elemento haciendo que el elemento no aparezca oculto.

AlwaysALearner
fuente
31
Sugerencia: Al eliminar el elemento HTML con ng-ifel modelo, agregado por ng-model, ya no existe.
mrzmyr
3
@CodeHater He aprovechado con éxito ng-if sobre ng-show / ng-hide en una página que de otro modo habría tenido un gran dominio. Parecía hacer que la página se sintiera más rápida, pero de ninguna manera es un análisis científico.
Ed Spencer
La parte con la que tengo problemas para comprender completamente es cómo / por qué cuando tienes un objeto en el modelo data.inputfunciona ... pero datasolo en el modelo no funciona. @CodeHater
Mark Pieszak - Trilon.io
77
@mcpDESIGNS ngIfcrea un nuevo ámbito, por lo que mirar el ejemplo anterior anidado ngModelcrearía un nuevo datamodelo aunque exista un modelo con el mismo nombre en el ámbito principal. Pero cuando usa una notación de puntos, hace que JS busque la cadena de prototipos del osciloscopio. Por lo tanto, si no encuentra el valor en el ámbito actual, intentará buscarlo en el ámbito primario y así sucesivamente. Algunas otras directivas que crean un ámbito diferente son ngInclude, ngRepeat. Espero que esté claro ahora. :)
AlwaysALearner
3
¿Cuál es mejor para el rendimiento? Creo que ng-show y ng-hide no es así?
tom10271
97

Quizás un punto interesante es la diferencia entre las prioridades entre ambos.

Por lo que puedo decir, la directiva ng-if tiene una de las prioridades más altas (si no la más alta) de todas las directivas angulares. Lo que significa: se ejecutará PRIMERO antes que todas las demás directivas de menor prioridad. El hecho de que se ejecuta PRIMERO significa que, efectivamente, el elemento se elimina antes de que se procesen las directivas internas . O al menos: eso es lo que hago con eso.

Observé y usé esto en la interfaz de usuario que estoy construyendo para mi cliente actual. Toda la interfaz de usuario está bastante llena, y tenía ng-show y ng-hide por todas partes. No voy a entrar en demasiados detalles, pero construí un componente genérico, que podría gestionarse utilizando la configuración JSON, por lo que tuve que hacer algunos cambios dentro de la plantilla. Hay un ng-repeat presente, y dentro del ng-repeat, se muestra una tabla, que tiene muchos ng-shows, ng-hides e incluso ng-switches presentes. Querían mostrar al menos 50 repeticiones en la lista, lo que daría como resultado la resolución de más o menos 1500-2000 directivas. Verifiqué el código, y el backend de Java + JS personalizado en el frente tardaría unos 150 ms en procesar los datos, y luego Angular masticaría unos 2-3 segundos antes de mostrarlo. El cliente no se quejó, pero me horroricé :-)

En mi búsqueda, me topé con la directiva ng-if. Ahora, tal vez sea mejor señalar que al momento de concebir esta IU, no había ng-if disponible. Debido a que ng-show y ng-hide tenían funciones en ellos, que devolvieron booleanos, podría reemplazarlos fácilmente con ng-if. Al hacerlo, todas las directivas internas ya no parecían evaluadas. Eso significaba que volví a un tercio de todas las directivas que se estaban evaluando y, por lo tanto, la IU aceleró hasta aproximadamente 500 ms - 1 segundo de tiempo de carga. (No tengo forma de determinar segundos exactos)

Tenga en cuenta: el hecho de que las directivas no se evalúen, es una suposición educada sobre lo que está sucediendo debajo.

Entonces, en mi opinión: si necesita que el elemento esté presente en la página (es decir, para verificar el elemento, o lo que sea), pero simplemente estar oculto, use ng-show / ng-hide. En todos los demás casos, use ng-if.

gjoris
fuente
1
Sí, supongo que este es el objetivo de ng-if: disminuir el tiempo de procesamiento. Esta directiva existe con seguridad no solo debido a algunos pseudoelectores CSS. ¡Buen post! +1
Bartłomiej Zalewski
16

@EdSpencer es correcto. Si tiene muchos elementos y usa ng-if solo para crear una instancia de los relevantes, está ahorrando recursos. @CodeHater también es algo correcto, si va a eliminar y mostrar un elemento muy a menudo, ocultarlo en lugar de eliminarlo podría mejorar el rendimiento.

El principal caso de uso que encuentro para ng-if es que me permite validar limpiamente y eliminar un elemento si el contenido es ilegal. Por ejemplo, podría hacer referencia a una variable de nombre de imagen nula y arrojará un error, pero si hago ng-if y compruebo si es nula, todo está bien. Si hice un ng-show, el error aún se dispararía.

AturSams
fuente
7

Una cosa importante a tener en cuenta sobre ng-if y ng-show es que cuando se usan controles de formulario, es mejor usarlo ng-ifporque elimina completamente el elemento del dom.

Esta diferencia es importante porque si crea un campo de entrada required="true"y luego lo configura ng-show="false"para ocultarlo, Chrome arrojará el siguiente error cuando el usuario intente enviar el formulario:

An invalid form control with name='' is not focusable.

La razón es que el campo de entrada está presente y lo está, requiredpero dado que está oculto, Chrome no puede enfocarse en él. Esto literalmente puede romper su código ya que este error detiene la ejecución del script. ¡Así que ten cuidado!

supersan
fuente
Este es el hecho real, si está utilizando controles de formulario para la validación, sufrirá mucho si usa ng-show / ng-hide. Y si tiene varias secciones ocultas / mostrar basadas en la expresión. Entonces, si usa ng-show / hide, los elementos seguirán allí y la validación fallará, a pesar de que no estén en la pantalla. así que ng-if rescatarte :)
NeverGiveUp161
5

@Gajus Kuizinas y @CodeHater son correctos. Aquí solo estoy dando un ejemplo. Mientras trabajamos con ng-if, si el valor asignado es falso, todos los elementos html se eliminarán de DOM. y si el valor asignado es verdadero, los elementos html serán visibles en el DOM. Y el alcance será diferente en comparación con el alcance principal. Pero en el caso de ng-show, solo mostrará y ocultará los elementos en función del valor asignado. Pero siempre se queda en el DOM. Solo la visibilidad cambia según el valor asignado.

http://plnkr.co/edit/3G0V9ivUzzc8kpLb1OQn?p=preview

Espero que este ejemplo lo ayude a comprender los alcances. Intente dar valores falsos a ng-show y ng-if y verifique el DOM en la consola. Intente ingresar los valores en los cuadros de entrada y observe la diferencia.

<!DOCTYPE html>

Hola plunker

<input type="text" ng-model="data">
<div ng-show="true">
    <br/>ng-show=true :: <br/><input type="text" ng-model="data">
</div>
<div ng-if="true">
    <br/>ng-if=true :: <br/><input type="text" ng-model="data">
</div> 
{{data}}


fuente
2

El hecho, esa ng-ifdirectiva, a diferencia ng-show, crea su propio alcance, conduce a una interesante diferencia práctica:

angular.module('app', []).controller('ctrl', function($scope){
  $scope.delete = function(array, item){
    array.splice(array.indexOf(item), 1);
  }
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app='app' ng-controller='ctrl'>
   <h4>ng-if:</h4>
   <ul ng-init='arr1 = [1,2,3]'>
      <li ng-repeat='x in arr1'>
        {{show}}
        <button ng-if='!show' ng-click='show=!show'>Delete {{show}}</button>
        <button ng-if='show' ng-click='delete(arr1, x)'>Yes {{show}}</button>
        <button ng-if='show' ng-click='show=!show'>No</button>
      </li>
   </ul>
   
   <h4>ng-show:</h4>
   <ul ng-init='arr2 = [1,2,3]'>
      <li ng-repeat='x in arr2'>
        {{show}}
        <button ng-show='!show' ng-click='show=!show'>Delete {{show}}</button>
        <button ng-show='show' ng-click='delete(arr2, x)'>Yes {{show}}</button>
        <button ng-show='show' ng-click='show=!show'>No</button>
      </li>
   </ul>
   
   <h4>ng-if with $parent:</h4>
    <ul ng-init='arr3 = [1,2,3]'>
      <li ng-repeat='item in arr3'>
        {{show}}
        <button ng-if='!show' ng-click='$parent.show=!$parent.show'>Delete {{$parent.show}}</button>
        <button ng-if='show' ng-click='delete(arr3, x)'>Yes {{$parent.show}}</button>
        <button ng-if='show' ng-click='$parent.show=!$parent.show'>No</button>
      </li>
   </ul>
</div>

En la primera lista, el on-clickevento, la showvariable, desde el ámbito interno / propio , se cambia, pero ng-ifestá observando otra variable desde el ámbito externo con el mismo nombre, por lo que la solución no funciona. En el caso de ng-showque tengamos la única showvariable, es por eso que funciona. Para solucionar el primer intento, debemos hacer referencia a showpartir de los padres / ámbito exterior a través $parent.show.

Slava Utesinov
fuente
1
  1. ng-if if false eliminará elementos del DOM. Esto significa que todos sus eventos, directivas adjuntas a esos elementos se perderán. Por ejemplo, ng-clic en uno de los elementos secundarios, cuando ng-if se evalúa como falso, ese elemento se eliminará del DOM y, de nuevo, cuando sea verdadero, se volverá a crear.

  2. ng-show / ng-hide no elimina los elementos del DOM. Utiliza estilos CSS (.ng-hide) para ocultar / mostrar elementos. De esta manera, sus eventos, directivas que se adjuntaron a los niños no se perderán.

  3. ng-if crea un ámbito secundario mientras que ng-show / ng-hide no lo hace.

Amay Kulkarni
fuente
1

ng-show y ng-hide funcionan de manera opuesta. Pero la diferencia entre ng-hide o ng-show con ng-if es que, si usamos ng-if, el elemento se creará en el dom pero con el elemento ng-hide / ng-show se ocultará por completo.

ng-show=true/ng-hide=false:
Element will be displayed

ng-show=false/ng-hide=true:
element will be hidden

ng-if =true
element will be created

ng-if= false
element will be created in the dom. 
usuario1001
fuente
0

Para tener en cuenta, algo que me sucedió ahora: ng-show oculta el contenido a través de css, sí, pero resultó en extrañas fallas en los div que se supone que son botones.

Tenía una tarjeta con dos botones en la parte inferior y, dependiendo del estado real, uno se intercambia con un tercer botón de edición de ejemplo con una nueva entrada. Usando ng-show = false para ocultar el izquierdo (presente primero en el archivo) sucedió que el siguiente botón terminó con el borde derecho fuera de la tarjeta. ng-if arregla eso al no incluir el código en absoluto. (Solo marque aquí si hay algunas sorpresas ocultas usando ng-if en lugar de ng-show)

helio
fuente
0

ngIf realiza una manipulación en el DOM eliminando o recreando el elemento.

Mientras que ngShow aplica reglas css para ocultar / mostrar cosas.

Para la mayoría de los casos (no siempre) , resumiría esto como, si necesita una verificación única para mostrar / ocultar cosas, use ng-if, si necesita mostrar / ocultar cosas según las acciones del usuario en la pantalla (como marcado una casilla de verificación y luego mostrar el cuadro de texto, desmarcar y luego ocultar el cuadro de texto, etc.), luego usarng-show

curioso
fuente
-17

Una diferencia interesante en ng-if y ng-show es:

SEGURIDAD

Los elementos DOM presentes en el bloque ng-if no se representarán en caso de que su valor sea falso

donde, como en el caso de ng-show, el usuario puede abrir su ventana Inspeccionar elemento y establecer su valor en VERDADERO.

Y con un grito, se muestra todo el contenido que estaba destinado a estar oculto, lo cual es una violación de seguridad. :)

Ashish_B
fuente
27
Esta es una forma de seguridad extremadamente débil. Si el servidor proporciona el contenido al cliente, debe suponer que el usuario / atacante puede acceder a él, independientemente de si está presente o no en el DOM. Toda la lógica de autorización debe ser aplicada por el servidor.
tlrobinson
piense en html en lugar de jsp ... ahora si desea aplicar la seguridad en los componentes html ... es decir, si desea ocultar algunos componentes del usuario ... ¿cómo lo lograría? Y en caso de que su configuración se divida en el lado del servidor para el backend y el lado del cliente para el front-end ..
Ashish_B