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.