As vezes caímos em alguma situação que um determinado evento aciona uma porção de regras dentro do seu “ViewModel”, e por consequência sua página trava, vamos analisar um exemplo simples desse cenário, e ver como resolver. Defina o “ViewModel” da seguinte forma (Veja o exemplo em Exemplo):
function ViewModel(){ var self = this; self.itens = ko.observableArray(); self.preencherItens = function(){ self.itens.removeAll(); for(var i = 1; i <= 1000; i++){ self.itens.push('Item ' + i); } } } ko.applyBindings(new ViewModel());
Acima temos um “ViewModel” com um “observableArray” chamado “itens” e um método que remove todos itens de “itens”, e posteriormente adiciona 1000 itens novos.
Vamos ver como fica o html:
<button data-bind="click: preencherItens">Preencher itens</button> <ul data-bind="foreach: itens"> <li data-bind="text: $data"></li> </ul>
Acima temos um botão que chama o método “preencherItens”, no click do botão, e um “ul” com todos os elementos do observable array “itens”.
Se clicarmos no botão “Preencher itens”, vamos perceber que a página “trava” por um pequeno período, isso ocorre porque o view está renderizando enquanto os dados de “itens” mudam.
Para resolver isso devemos desabilitar as notificações para view, e assim que o processo finalizar, devemo avisar que a view já pode ser renderizada. Veja no exemplo Exemplo 2
Vamos alterar o método “preencherItens” para:
self.preencherItens = function(){ var itens = self.itens(); self.itens.valueWillMutate(); self.itens.removeAll(); for(var i = 1; i <= 1000; i++){ itens.push('Item ' + i); } self.itens.valueHasMutated(); }
Acima definimos que o observable array “itens” deve ser referenciado pela variável “itens” (isso é particularmente importante, se acessarmos o array observable direto, a view será renderizada da mesma forma como antes).
Em seguida executamos o método nativo do knockout “valueWillMutate”, isso “avisará” que o observable sofrerá mutações, e deve aguardar um aviso para voltar a renderizar.
Na linha abaixo removemos todos os itens do array e através do comando de repetição adicionamos 1000 itens na variável “itens” (repare que não referenciamos o array observable diretamente)
Em seguida “avisamos” o array observable que os dados sofreram uma mutação e pode voltar a renderizar na tela.
Se clicarmos em “Preencher itens”, vamos perceber que a impressão que fica, é que o método executou muito mais rápido do que o primeiro exemplo, quando na realidade apenas desabilitamos a renderização por um determinado período.