Desculpe se isso já foi respondido aqui, mas não encontrei nenhuma correspondência para o nosso cenário específico, então aqui vai!
Tivemos uma discussão em nossa equipe de desenvolvimento, sobre chamadas de função em modelos angulares. Agora, como regra geral, concordamos que você não deve fazer isso. No entanto, tentamos discutir quando pode estar tudo bem. Deixe-me dar um cenário.
Digamos que temos um bloco de modelo envolvido em um ngIf, que verifica vários parâmetros, como aqui:
<ng-template *ngIf="user && user.name && isAuthorized">
...
</ng-template>
Haveria uma diferença significativa no desempenho em comparação com algo como isto:
Modelo:
<ng-template *ngIf="userCheck()">
...
</ng-template>
Texto datilografado:
userCheck(): boolean {
return this.user && this.user.name && this.isAuthorized;
}
Então, para resumir a pergunta, a última opção teria algum custo de desempenho significativo?
Preferimos usar a segunda abordagem, em situações em que precisamos verificar mais de duas condições, mas muitos artigos online dizem que as chamadas de funções SEMPRE são ruins nos modelos, mas será realmente um problema nesse caso?
fonte
Respostas:
Eu também tentei evitar chamadas de funções nos modelos o máximo possível, mas sua pergunta me inspirou a fazer uma pesquisa rápida:
Adicionei outro caso com
userCheck()
resultados de cachePreparou uma demonstração aqui: https://stackblitz.com/edit/angular-9qgsm9
Surpreendentemente, parece que não há diferença entre
E
E
Parece válido para uma verificação de propriedade simples, mas definitivamente haverá uma diferença se houver alguma
async
ação, getters que estão esperando por alguma API, por exemplo.fonte
Esta é uma resposta bastante opinativa.
O uso de funções como essa é perfeitamente aceitável. Isso tornará os modelos muito mais claros e não causará nenhuma sobrecarga significativa. Como o JB disse antes, ele também estabelecerá uma base muito melhor para testes de unidade.
Também acho que qualquer expressão que você tenha no seu modelo será avaliada como uma função pelo mecanismo de detecção de alterações, portanto, não importa se você a possui no modelo ou na lógica do componente.
Apenas mantenha a lógica dentro da função no mínimo. Se você estiver no entanto cauteloso sobre qualquer impacto no desempenho essa função um pode ter, eu recomendo fortemente que você colocar o seu
ChangeDetectionStrategy
paraOnPush
, que é considerada a melhor prática de qualquer maneira. Com isso, a função não será chamada a cada ciclo, somente quando umaInput
alteração, algum evento ocorrer dentro do modelo, etc.(usando etc, porque não conheço mais o outro motivo) .
Pessoalmente, novamente, acho que é ainda melhor usar o padrão Observables; você pode usar o
async
pipe e, somente quando um novo valor é emitido, o modelo é reavaliado:Você pode apenas usar no modelo como este:
Ainda outra opção seria usar
ngOnChanges
, se todas as variáveis dependentes do componente forem Entradas, e você tiver muita lógica para calcular uma determinada variável de modelo (que não é o caso que você mostrou):Que você pode usar no seu modelo assim:
fonte
Observable
fluxo, o que o tornará um candidato perfeito para a segunda opção que mostrei. De qualquer forma, fico feliz por poder lhe dar algumas idéiasNão é recomendado por muitos motivos o principal:
Para determinar se o userCheck () precisa ser renderizado novamente, o Angular precisa executar a expressão userCheck () para verificar se o valor de retorno foi alterado.
Como o Angular não pode prever se o valor de retorno de userCheck () foi alterado, ele precisa executar a função sempre que a detecção de alterações for executada.
Portanto, se a detecção de alterações for executada 300 vezes, a função será chamada 300 vezes, mesmo que seu valor de retorno nunca seja alterado.
Explicação estendida e mais problemas https://medium.com/showpad-engineering/why-you-should-never-use-function-calls-in-angular-template-expressions-e1a50f9c0496
O problema ocorre quando se o seu componente é grande e participa de muitos eventos de mudança, se o componente for pequeno e apenas participar de alguns eventos não deve ser um problema.
Exemplo com observáveis
Então você pode usá-lo como observável com o canal assíncrono no seu código.
fonte
Penso que o JavaScript foi criado com um objetivo para que um desenvolvedor não note a diferença entre uma expressão e uma chamada de função em relação ao desempenho.
Em C ++, há uma palavra
inline
- chave para marcar uma função. Por exemplo:Isso foi feito para eliminar uma chamada de função. Como resultado, o compilador substitui todas as chamadas
userCheck
pelo corpo da função. Razão para inovarinline
? Um aumento de desempenho.Portanto, acho que o tempo de execução de uma chamada de função com uma expressão, provavelmente, é mais lento que a execução da expressão. Mas também acho que você não notará uma diferença no desempenho se tiver apenas uma expressão na função.
fonte