Quando favorecer ng-if vs. ng-show / ng-hide?

Respostas:

703

Depende do seu caso de uso, mas para resumir a diferença:

  1. ng-ifremoverá elementos do DOM. Isso significa que todos os seus manipuladores ou qualquer outra coisa anexada a esses elementos serão perdidos. Por exemplo, se você vincular um manipulador de cliques a um dos elementos filhos, quando for ng-ifavaliado como falso, esse elemento será removido do DOM e o manipulador de cliques não funcionará mais, mesmo depois que ng-ifavaliar como true e exibir o elemento. Você precisará reconectar o manipulador.
  2. ng-show/ng-hidenão remove os elementos do DOM. Ele usa estilos CSS para ocultar / mostrar elementos (nota: você pode precisar adicionar suas próprias classes). Dessa forma, seus manipuladores anexados a crianças não serão perdidos.
  3. ng-ifcria um escopo filho enquanto ng-show/ng-hidenão

Os elementos que não estão no DOM têm menos impacto no desempenho e seu aplicativo Web pode parecer mais rápido quando usado em ng-ifcomparação com ng-show/ng-hide. Na minha experiência, a diferença é insignificante. As animações são possíveis ao usar ambos ng-show/ng-hidee ng-if, com exemplos para ambos na documentação Angular.

Por fim, a pergunta que você precisa responder é se você pode remover o elemento do DOM ou não?

markovuksanovic
fonte
19
Você pode usar animações CSS3 com ng-if. Verifique o parágrafo Animações e o exemplo nos documentos . Também com ng-hide/ng-showos seletores de CSS como :first-childou :nth-childnão funcionarão corretamente, pois os elementos ocultos também serão contados.
Łukasz Wojciechowski
4
O serviço de animação em angular.dart é relativamente novo. No momento em que escrevi isso, não estava disponível.
MarkVuksanovic 17/03/2014
44
Seu primeiro ponto é um problema se você estiver usando diretivas (como ng-click) para vincular manipuladores, como deveria.
18714 Kevin Kevin C.
9
Além disso, ng-ifcria um novo escopo enquanto ng-shownão.
martin
8
Também deve ser mencionado que a adição e remoção de elementos do DOM pode resultar em um alto custo de desempenho, se feito com freqüência.
Kevin C.
130

Veja aqui um CodePen que demonstra a diferença de como o ng-if / ng-show funciona, em termos de DOM.

@markovuksanovic respondeu bem à pergunta. Mas eu chegaria a isso de outra perspectiva: eu sempre usava ng-ife tirava esses elementos do DOM, a menos que:

  1. por algum motivo, você precisa das associações de dados e $watch-es em seus elementos para permanecer ativo enquanto eles estão invisíveis. Os formulários podem ser um bom argumento para isso, se você quiser verificar a validade das entradas que não estão visíveis no momento, para determinar se o formulário inteiro é válido.
  2. Você está usando uma lógica stateful realmente elaborada com manipuladores de eventos condicionais, como mencionado acima. Dito isto , se você se encontra anexando e desanexando manualmente manipuladores, de modo a perder um estado importante ao usar ng-if, pergunte-se se esse estado seria melhor representado em um modelo de dados e os manipuladores aplicados condicionalmente por diretivas sempre que o elemento é renderizado. Em outras palavras, a presença / ausência de manipuladores é uma forma de dados de estado. Tire esses dados do DOM e entre em um modelo. A presença / ausência dos manipuladores deve ser determinada pelos dados e, portanto, fácil de recriar.

Angular está escrito muito bem. É rápido, considerando o que faz. Mas o que ele faz é um monte de mágica que faz coisas difíceis (como ligação de dados bidirecional) parecerem trivialmente fáceis. Fazer com que todas essas coisas pareçam fáceis implica alguma sobrecarga de desempenho. Você pode ficar chocado ao perceber quantas centenas ou milhares de vezes uma função setter é avaliada durante o $digestciclo em um pedaço de DOM que ninguém está olhando. E então você percebe que tem dezenas ou centenas de elementos invisíveis, todos fazendo a mesma coisa ...

Os desktops podem realmente ser poderosos o suficiente para tornar a maioria dos problemas de velocidade de execução de JS discutíveis. Mas se você estiver desenvolvendo para dispositivos móveis, usar ng-if sempre que humanamente possível deve ser um acéfalo. A velocidade do JS ainda é importante nos processadores móveis. Usar ng-if é uma maneira muito fácil de obter otimização potencialmente significativa a um custo muito, muito baixo.

XML
fonte
6
Adição muito agradável à resposta acima. Dado com algum bom contexto, o que também ajuda na tomada de decisão. Obrigado.
Sean
1
ng-showpode ser útil quando você tiver, digamos, guias cada uma com muito conteúdo que leva tempo para renderizar. Após a primeira renderização, a movimentação entre as guias será instantânea, ao passo ng-ifque exigiria nova renderização, eventos de ligação etc. A desvantagem, como você diz, é que cria relógios sendo executados em segundo plano. Angular precisa desesperadamenteng-ifshowwatch
poshest
53

Da minha experiência:

1) Se sua página tiver uma alternância que usa ng-if / ng-show para mostrar / ocultar algo, ng-if causa mais atraso no navegador (mais lento). Por exemplo: se você tem um botão usado para alternar entre duas visualizações, o ng-show parece ser mais rápido.

2) ng-if criará / destruirá o escopo quando for avaliado como verdadeiro / falso. Se você tiver um controlador conectado ao ng-if, esse código será executado toda vez que o ng-if for avaliado como verdadeiro. Se você estiver usando o ng-show, o código do controlador será executado apenas uma vez. Portanto, se você tiver um botão que alterna entre várias visualizações, o uso de ng-if e ng-show faria uma enorme diferença na maneira como você escreve o código do seu controlador.

Yi Z
fonte
5
Isso é uma enorme verdade! ng-if não necessariamente torna seu front-end mais rápido. Isso depende de suas necessidades. Na verdade, poderia fazer o contrário, se você estiver usando na situação errada.
Thiago C. S Ventura
1
Mas, na minha opinião, o ng-if não é renderizado no DOM, portanto é rápido em comparação com o ng-show / hide. Estou errado pls, deixe-me corrigir nesse ponto.
precisa
1
ng-if seria mais rápido se avaliado como falso, pois, como você diz, nada precisa ser inserido no DOM. Mas, se for verdade, você terá uma sobrecarga de inserção do elemento - possivelmente bastante complicado - no DOM.
Mawg diz que restabelece Monica 15/02/16
"2) ng-if criará / destruirá o escopo quando for avaliado como verdadeiro / falso. Se você tiver um controlador anexado ao ng-if, esse código será executado toda vez que o"
The Red Pea
35

A resposta não é simples:

Depende das máquinas de destino (móvel x desktop), depende da natureza dos seus dados, navegador, sistema operacional, hardware em que é executado ... você precisará avaliar se realmente deseja saber.

É principalmente um problema de memória versus computação ... como na maioria dos problemas de desempenho, a diferença pode se tornar significativa com elementos repetidos (n) como listas, especialmente quando aninhados (nxn ou pior) e também que tipo de computação você executa dentro desses elementos :

  • ng-show : se esses elementos opcionais estiverem frequentemente presentes (densos), como por exemplo 90% das vezes, pode ser mais rápido tê-los prontos e apenas mostrá-los / ocultá-los, especialmente se o conteúdo for barato (apenas texto simples, nada para calcular ou carregar). Isso consome memória, pois preenche o DOM com elementos ocultos, mas apenas mostrar / ocultar algo que já existe provavelmente será uma operação barata para o navegador.

  • ng-if : Se, pelo contrário, é provável que os elementos não sejam mostrados (esparsos), apenas construa-os e destrua-os em tempo real, especialmente se seu conteúdo for caro (computações / classificadas / filtradas, imagens, imagens geradas). Isso é ideal para elementos raros ou "sob demanda", economiza memória em termos de não preencher o DOM, mas pode custar muita computação (criação / destruição de elementos) e largura de banda (obtenção de conteúdo remoto). Também depende de quanto você calcula na visualização (filtragem / classificação) versus o que você já possui no modelo (dados pré-classificados / pré-filtrados).

Christophe Roussy
fonte
2
Outras respostas para fatos técnicos. Este por sabedoria. Você criou claramente aplicativos angulares não triviais, senhor! 1
poshest
Esse problema vai além do angular, é um problema fundamental na ciência da computação, há um ponto em que um método é mais eficiente que o outro. Geralmente, isso pode ser encontrado através de alguns testes comparativos. Para que você possa alternar entre um método e outro, dependendo da contagem de itens ... Tópico semelhante: math.stackexchange.com/questions/1632739/…
Christophe Roussy
12

Uma observação importante:

ngIf (diferentemente do ngShow) geralmente cria escopos filhos que podem produzir resultados inesperados.

Eu tive um problema relacionado a isso e passei MUITO tempo para descobrir o que estava acontecendo.

(Minha diretiva estava gravando seus valores de modelo no escopo errado.)

Portanto, para economizar seu cabelo, use o ngShow, a menos que você corra muito devagar.

De qualquer forma, a diferença de desempenho é quase imperceptível e ainda não tenho certeza de quem é o favor sem um teste ...

user2173353
fonte
8
Usando $parent.scopevarem ligações de dados dentro de uma ngIf irá corrigir coisas como questões criança escopos ao usar ngIf
meconroy
2
Isso não é totalmente verdade (isto é, o comentário original do @ user2173353). Se você seguir as boas práticas, não terá problemas. Essa é uma regra bastante básica: "se não houver ponto, você estará fazendo errado". Veja aqui uma demonstração de como funciona: bit.ly/1SPv4wL . Outra ótima referência (consulte o erro nº 2): bit.ly/1QfFeWd > (Minha diretiva estava gravando seus valores de modelo no escopo errado.) Esse é o resultado de não seguir a prática acima.
piotr.d
1
@ piotr.d Você está certo, mas isso não é algo em que um iniciante possa se concentrar e há outra prática recomendada que diz que é melhor deixar melhorias de desempenho para o final (especialmente melhorias de desempenho que podem não ser melhorias na realidade ) Vi pessoas colocando em ngIftodos os lugares acreditando que isso melhorará o desempenho. Isso simplesmente não é verdade e não se pode dizer qual é o melhor, ngIfou ngShow, sem um teste ou uma análise profunda no caso particular. Então, eu ainda recomendo esquecendo-se ngIf, até que se vê mau desempenho ou sabe o que está fazendo
user2173353
2
Bom ponto. Mas usar controllerAs torna isso um problema. Veja, por exemplo, a opinião de John Papa sobre controllerAs e vm .
Jsruok
4

ng-if em ng-include e no ng-controller terão um grande impacto sobre ng-include, ele não carregará a parcial necessária e não será processada, a menos que o sinalizador seja verdadeiro no ng-controller, não carregará o controlador a menos que o sinalizador seja true, mas o problema é quando um sinalizador fica falso em ng - se ele for removido do DOM quando o sinalizador voltar verdadeiro, recarregará o DOM neste caso, ng-show é melhor, por uma vez mostre ng-se é melhor

Saad Ahmed
fonte
4

Se você usar ng-show or ng-hideo conteúdo (por exemplo, miniaturas do servidor), será carregado independentemente do valor da expressão, mas será exibido com base no valor da expressão.

Se você usar, ng-ifo conteúdo será carregado apenas se a expressão do ng-if for avaliada como verdadeira.

Usar ng-if é uma boa ideia em uma situação em que você irá carregar dados ou imagens do servidor e mostrá-los apenas dependendo da interação do usuário. Dessa forma, o carregamento da sua página não será bloqueado por tarefas desnecessárias e desnecessárias.

appdroid
fonte
Isso é especialmente útil, pois a maioria dos navegadores carrega imagens, mesmo que o CSS oculte seus contêineres DOM. Eles geralmente apenas procuram o srcatributo da imgtag, quando presente, ela é carregada!
Christophe Roussy