DEV Community

Como funcionam Bindings de Fluxo de Controle no KnockoutJs

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


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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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 bloco foreach é duplicado e inserido no documento, tanto quando foreach é inicializado pela primeira vez quanto quando novas entradas são adicionadas posteriormente ao array associado;
  • afterAdd: é como afterRender, exceto que é invocado apenas quando novas entradas são adicionadas ao array (e não quando foreach 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 chamada beforeRemove, 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 que beforeMove 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 o beforeMove 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 que foreach atualizou o DOM para corresponder. Observe que afterMove 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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

Top comments (0)