Como funcionam Bindings de Fluxo de Controle no KnockoutJs
Lucas Teixeira dos Santos Santana
Posted on November 18, 2024
Este conteúdo é basicamente uma tradução dos materiais originais. A intenção é adquirir aprendizado sobre o KnockoutJs para Magento 2 e criar conteúdo em português sobre KnockouJs.
Documentação
- The data-bind syntax
- Binding context
- The "foreach" binding
- The "if" and "ifnot" bindings
- The "with" and "using" bindings
- The "let" binding
Bindings
No KnockoutJs, bindings são a maneira de conectar a lógica do ViewModel (os dados e a lógica de negócios) com a View (HTML). Em resumo, é através dos bindings que é realizada a interface de usuário refletir automaticamente as mudanças nos seus dados, sem a necessidade de manipular diretamente o DOM.
Os bindings no KnockoutJs funcionam através do atributo data-bind
em elementos HTML. Esse atributo é onde você especifica o binding que deseja usar e os valores associados.
Fluxo de Controle
foreach
O binding foreach
é usado para criar repetições em elementos HTML, gerando cópias do mesmo elemento para cada item em uma coleção (como um array ou um observable array) no seu modelo de visualização. Isso permite que seja criado facilmente listas ou tabelas dinâmicas que exibem dados do seu modelo.
Quando é modificado o conteúdo do array de modelo (adicionando, movendo ou excluindo suas entradas), o binding do foreach usa um algoritmo eficiente para descobrir o que mudou, para que possa atualizar o DOM conforme o array. Isso significa que ele pode lidar com combinações arbitrárias de alterações simuladas.
- Quando é adicionado algo no array, o
foreach
irá renderizar novas cópias do seu modelo e inseri-las no DOM existente; - Quando é excluído algo no array, o
foreach
simplesmente removerá os elementos DOM correspondentes; - Quando é reordenado algo no array (mantendo as mesmas instâncias do objeto), o
foreach
normalmente apenas moverá os elementos DOM correspondentes para sua nova posição.
<div>
<ul data-bind="foreach: items">
<li data-bind="text: $data"></li>
</ul>
<ul data-bind="foreach: getItems()">
<li>
<span data-bind="text: name"></span> - <span data-bind="text: age"></span>
</li>
</ul>
<ul data-bind="foreach: { data: people, as: 'person' }"></ul>
</div>
Neste caso, a variável $data
faz referência ao item atual que está sendo processado no loop. Isso permite acessar as propriedades ou valores desse item dentro do loop.
A diretiva as
permite que seja definido um nome personalizado para a variável que representa o item atual no ciclo de iteração do foreach
. Isso pode tornar o código mais legível e significativo.
Às vezes é necessário que um item do array não seja excluído, mas sim ocultado, sem realmente perder o registro de sua existência. Isso é conhecido como exclusão não destrutiva. Caso seja necessário ocultar entradas destruídas, defina a opção includeDestroyed
como false
.
<div data-bind='foreach: { data: myArray, includeDestroyed: false }'>
...
</div>
Caso seja necessário executar alguma lógica personalizada adicional nos elementos DOM gerados, é possível usar qualquer um dos seguintes retornos de chamada:
-
afterRender
: é invocado cada vez que o blocoforeach
é duplicado e inserido no documento, tanto quando foreach é inicializado pela primeira vez quanto quando novas entradas são adicionadas posteriormente ao array associado; -
afterAdd
: é comoafterRender
, exceto que é invocado apenas quando novas entradas são adicionadas ao array (e não quandoforeach
itera pela primeira vez sobre o conteúdo inicial do array); -
beforeRemove
: é invocado quando um item do array é removido, mas antes que os nós DOM correspondentes sejam removidos. Se for especificado um retorno de chamadabeforeRemove
, será necessário remover os nós DOM manualmente, ou seja, o KnockoutJs não pode saber quando será permitido remover fisicamente os nós DOM; -
beforeMove
: é invocado quando um item do array mudou de posição no array, mas antes que os nós DOM correspondentes tenham sido movidos. Observe quebeforeMove
se aplica a todos os elementos do array cujos índices foram alterados, portanto, se for inserido um novo item no início de um array, o retorno de chamada (se especificado) será acionado para todos os outros elementos, já que sua posição de índice aumentou em um. É possível usar obeforeMove
para armazenar as coordenadas originais da tela dos elementos afetados para poder animar seus movimentos no retorno de chamada afterMove; -
afterMove
: é invocado depois que um item do array mudou de posição no array e depois queforeach
atualizou o DOM para corresponder. Observe queafterMove
se aplica a todos os elementos do array cujos índices foram alterados, portanto, se for inserido um novo item no início de um array, o retorno de chamada (se especificado) será acionado para todos os outros elementos, já que sua posição de índice aumentou em um.
if e ifnot
O binding do if
faz com que uma seção de marcação apareça em seu documento (e tenha seus atributos de ligação de dados aplicados), somente se uma expressão especificada for avaliada como verdadeira (ou um valor verdadeiro, como um objeto não nulo ou uma string não vazia).
O binding do ifnot
funciona exatamente como a ligação if
, exceto que inverte o resultado de qualquer expressão que seja passado para ela.
if
e ifnot
desempenham um papel semelhante aos bindings vivsible
e hidden
. A diferença é que, com visible
, a marcação contida sempre permanece no DOM e sempre tem seus data-bind
de dados aplicados – o binding visible
apenas usa CSS para alternar a visibilidade do elemento contêiner. A ligação if
, entretanto, adiciona ou remove fisicamente a marcação contida em seu DOM e só aplica ligações aos descendentes se a expressão for verdadeira. Se a expressão envolver algum valor observável, a expressão será reavaliada sempre que o valor dele mudar.
<div data-bind="if: exibirMensagem">
<p>Esta mensagem será exibida se 'exibirMensagem' for verdadeiro.</p>
</div>
<div data-bind="ifnot: exibirMensagem">
<p>Esta mensagem será exibida se 'exibirMensagem' for falso.</p>
</div>
with e using
Os bindings with
e using
criam um novo contexto de ligação, para que os elementos descendentes sejam vinculados no contexto de um objeto especificado.
O binding with
adicionará ou removerá dinamicamente elementos descendentes dependendo se o valor associado for falsy.
A opção as
permite definir um alias para o novo objeto de contexto. Embora seja possível se referir ao objeto usando a variável de contexto $data
.
<form data-bind="submit: getTweets">
Twitter account:
<input data-bind="value: twitterName" />
<button type="submit">Get tweets</button>
</form>
<div data-bind="with: resultData">
<h3>Recent tweets fetched at <span data-bind="text: retrievalDate"> </span></h3>
<ol data-bind="foreach: topTweets">
<li data-bind="text: text"></li>
</ol>
<button data-bind="click: $parent.clearResults">Clear tweets</button>
</div>
<script type="text/javascript">
function AppViewModel() {
var self = this;
self.twitterName = ko.observable('@example');
self.resultData = ko.observable(); // No initial value
self.getTweets = function() {
var name = self.twitterName(),
simulatedResults = [
{ text: name + ' What a nice day.' },
{ text: name + ' Building some cool apps.' },
{ text: name + ' Just saw a famous celebrity eating lard. Yum.' }
];
self.resultData({ retrievalDate: new Date(), topTweets: simulatedResults });
}
self.clearResults = function() {
self.resultData(undefined);
}
}
ko.applyBindings(new AppViewModel());
</script>
A ligação using
foi introduzida no KnockoutJs 3.5 como um substituto para o with
quando a renderização de elementos descendentes não é desejada. Como o using
reavalia as ligações descendentes em vez de renderizar novamente, cada ligação descendente incluirá uma dependência adicional no contexto do using
.
let
O binding let
permite definir propriedades de contexto de ligação personalizadas que é possível referenciar nas ligações de todos os elementos descendentes.
<!--ko let: {inventory: {suppliers: suppliers, bins: bins}, calculatedDisplay: someCalculation}-->
<div data-bind="foreach: {data: inventory.suppliers, as: 'supplier'}">
<div data-bind="foreach: {data: inventory.bins, as: 'bin'}">
<span data-bind="text: calculatedDisplay(supplier, bin)">
</div>
</div>
<!--/ko-->
<script type="text/javascript">
ko.applyBindings({
suppliers: [...],
bins: [...],
someCalculation: function (supplier, bin) {
/* return some calculated value based on parameters */
}
});
</script>
Posted on November 18, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.