KnockoutJS - Guia rápido

KnockoutJS é basicamente uma biblioteca escrita em JavaScript, baseada no padrão MVVM que ajuda os desenvolvedores a construir sites ricos e responsivos. O modelo separa o Modelo do aplicativo (dados armazenados), Visão (UI) e Modelo de Visão (Representação JavaScript do modelo).

KnockoutJS foi desenvolvido e é mantido como um projeto de código aberto por Steve Sanderson, um funcionário da Microsoft em 5 de julho de 2010. KO é uma abreviatura usada para KnockoutJS. KO suporta todos os navegadores convencionais - IE 6+, Firefox 3.5+, Chrome, Opera, Safari (desktop / móvel).

Recursos do KnockoutJS

Aqui está uma lista de alguns dos recursos mais importantes do KnockoutJS -

  • Declarative Binding- Os elementos HTML DOM são conectados ao modelo por meio do atributo data-bind usando uma sintaxe muito simples. É fácil alcançar a capacidade de resposta usando esse recurso.

  • Automatic UI Refresh- Quaisquer alterações feitas para visualizar os dados do modelo são refletidas na IU automaticamente e vice-versa. Não há necessidade de escrever código extra.

  • Dependency Tracking- A relação entre os atributos KO e as funções / componentes da biblioteca KO é transparente. Rastreia automaticamente as alterações de dados no atributo KO e atualiza as respectivas áreas afetadas.

  • Templating - Os modelos são uma maneira simples e conveniente de construir estruturas complexas de IU - com a possibilidade de repetir ou aninhar blocos - como uma função dos dados do modelo de visualização.

  • Extensible - Estende o comportamento personalizado com muita facilidade.

Por que usar o KnockoutJS?

  • A biblioteca KnockoutJS fornece uma maneira fácil e limpa de lidar com interfaces complexas baseadas em dados. Pode-se criar UIs de atualização automática para objetos Javascript.

  • É pura biblioteca JavaScript e funciona com qualquer estrutura da web. Não é um substituto do JQuery, mas pode funcionar como um suplemento, fornecendo recursos inteligentes.

  • O arquivo da biblioteca KnockoutJS é muito pequeno e leve.

  • KnockoutJS é independente de qualquer outra estrutura. É compatível com outras tecnologias de cliente ou servidor.

  • O mais importante de tudo KnockoutJS é open source e, portanto, gratuito para uso.

  • KnockoutJS está totalmente documentado. O site oficial possui documentação completa, incluindo documentos de API, exemplos ao vivo e tutoriais interativos.

É muito fácil usar o KnockoutJS. Simplesmente consulte o arquivo JavaScript usando a tag <script> nas páginas HTML.

Knockout.js pode ser acessado das seguintes maneiras -

  • Você pode baixar a versão de produção do Knockout.js em seu site oficial

    Uma página como na imagem a seguir será exibida. Clique no link de download e você obterá o arquivo knockout.js mais recente.

Agora consulte o arquivo conforme mostrado no código a seguir.

<script type = 'text/javascript' src = 'knockout-3.3.0.js'></script>

Atualize o atributo src para corresponder ao local onde os arquivos baixados são mantidos.

  • Você pode consultar a biblioteca KnockoutJS de CDNs -

    • Você pode consultar a biblioteca KnockoutJS do CDN do Microsoft Ajax em seu código da seguinte maneira -

<script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js" 
   type = "text/javascript"></script>
  • Como alternativa, você pode consultar uma versão reduzida da biblioteca KnockoutJS do CDNJS da seguinte forma -

<script src = "https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js" 
   type = "text/javascript"></script>

Note - Em todos os capítulos deste tutorial, nos referimos à versão CDN da biblioteca KnockoutJS.

Exemplo

KnockoutJS é baseado no padrão Model-View-ViewModel (MVVM). Vamos estudar esse padrão em profundidade no capítulo KnockoutJS - MVVM Framework . Primeiro, vamos dar uma olhada em um exemplo simples de KnockoutJS.

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Simple Example</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js" 
         type = "text/javascript"></script>
   </head>

   <body>
      <!-- This is called "view" of HTML markup that defines the appearance of UI -->

      <p>First String: <input data-bind = "value: firstString" /></p>
      <p>Second String: <input data-bind = "value: secondString" /></p>

      <p>First String: <strong data-bind = "text: firstString">Hi</strong></p>
      <p>Second String: <strong data-bind = "text: secondString">There</strong></p>

      <p>Derived String: <strong data-bind = "text: thirdString"></strong></p>

      <script>
         <!-- This is called "viewmodel". This javascript section defines the data and 
            behavior of UI -->

         function AppViewModel() {
            this.firstString = ko.observable("Enter First String");
            this.secondString = ko.observable("Enter Second String");

            this.thirdString = ko.computed(function() {
               return this.firstString() + " " + this.secondString();
            }, this);
         }

         // Activates knockout.js
         ko.applyBindings(new AppViewModel());
      </script>

   </body>
</html>

A linha a seguir se refere à biblioteca KnockoutJS.

<script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js" 
   type = "text/javascript"> </script>

Esta linha se refere à biblioteca KnockoutJS.

Temos duas caixas de entrada: First String e Second String. Essas 2 variáveis ​​são inicializadas com os valores Enter First String e Enter Second String respectivamente em ViewModel.

<p>First String: < input data-bind = "value: firstString" /> </p>

É assim que vinculamos valores de ViewModel a elementos HTML usando 'data-bind' atributo na seção do corpo.

Aqui, 'firstString' se refere à variável ViewModel.

this.firstString = ko.observable("Enter First String");

ko.observable é um conceito que fica de olho nas mudanças de valor para que possa atualizar os dados ViewModel subjacentes.

Para entender isso melhor, vamos atualizar a primeira caixa de entrada para "Olá" e a segunda caixa de entrada para "TutorialsPoint". Você verá que os valores são atualizados simultaneamente. Estudaremos mais sobre esse conceito no capítulo KnockoutJS - Observáveis .

this.thirdString = ko.computed(function() {
   return this.firstString() + " " + this.secondString();
}, this);

Em seguida, calculamos a função no viewmodel. Esta função deriva a terceira string com base nas 2 strings mencionadas anteriormente. Portanto, todas as atualizações feitas nessas strings são refletidas automaticamente nesta string derivada. Não há necessidade de escrever um código extra para fazer isso. Este é apenas um exemplo simples. Estudaremos este conceito no capítulo KnockoutJS - Computed Observables .

Resultado

Salve o código acima como my_first_knockoutjs_program.html. Abra este arquivo em seu navegador e você verá uma saída como a seguinte.

Modifique as strings para "Hello" e "TutorialsPoint" e a saída muda conforme a seguir.

KnockoutJS é amplamente usado para aplicativos de página única - um site criado com a capacidade de recuperar todos os dados necessários dinamicamente com um único carregamento de página, reduzindo as viagens de ida e volta do servidor.

KnockoutJS é uma estrutura do lado do cliente. Esta é uma biblioteca JavaScript que torna muito fácil vincular HTML a dados de domínio. Ele implementa um padrão chamado Model-View-ViewModel (MVVM). Observáveis ​​são o ingrediente mágico de KnockoutJS. Todos os dados permanecem sincronizados por causa do atributo Observable.

Arquitetura

Visão

A visualização nada mais é do que uma interface de usuário criada usando elementos HTML e estilos CSS.

Você pode vincular elementos HTML DOM ao modelo de dados usando KnockoutJS. Ele fornece ligação de dados bidirecional entre View e ViewModel usando o conceito de 'data-bind', o que significa que todas as atualizações feitas na IU são refletidas no modelo de dados e todas as mudanças feitas no modelo de dados são refletidas na IU. Pode-se criar uma IU de atualização automática com a ajuda de knockoutJS.

ViewModel

ViewModel é um objeto JavaScript, que contém propriedades e funções necessárias para representar dados. View e ViewModel são conectados com o conceito de data-bind declarativo usado em HTML. Isso torna mais fácil alterar o HTML sem alterar ViewModel. KnockoutJS cuida da atualização automática de dados entre eles por meio do uso de Observáveis.

A sincronização de dados é obtida por meio da vinculação de elementos DOM ao Modelo de Dados, primeiro usando vinculação de dados e, em seguida, atualizando esses 2 componentes por meio do uso de Observáveis. O rastreamento de dependência é feito automaticamente devido a esta sincronização de dados. Nenhuma codificação extra é necessária para alcançá-lo. KnockoutJS permite criar uma conexão direta entre o display e os dados subjacentes.

Você pode criar suas próprias ligações chamadas como ligações personalizadas para comportamentos específicos do aplicativo. Dessa forma, o Knockout oferece controle direto de como você deseja transformar seus dados em HTML.

Modelo

O modelo são os dados de domínio no servidor e são manipulados quando a solicitação é enviada / recebida do ViewModel.

Os dados podem ser armazenados em banco de dados, cookie ou outra forma de armazenamento persistente. KnockoutJS não se preocupa com a forma como ele é armazenado. Cabe ao programador a comunicação entre os dados armazenados e o KnockoutJS.

Na maioria das vezes, os dados são salvos e carregados por meio de uma chamada Ajax.

Model-View-ViewModel (MVVM)é um padrão de projeto arquitetônico para o desenvolvimento de aplicativos de software. MVVM foi desenvolvido pelo Microsoft Architect John Gossman em 2005. Este padrão é derivado do padrão Model-View-Controller (MVC). A vantagem do MVVM é que ele separa a interface gráfica do usuário da camada do aplicativo da lógica de negócios. O MVVM é responsável por manipular os dados do modelo subjacente de forma que sejam representados e gerenciados com muita facilidade. ViewModel em MVVM representa uma versão abstrata do estado e ações de View.

As classes de visão não sabem que as classes Model e ViewModel existem, também Model e ViewModel não sabem que a visão existe. Model também não sabe que ViewModel e View existem.

Arquitetura

Visão

View é uma interface gráfica de usuário criada usando linguagem de marcação para representar dados. View se vincula às propriedades de um ViewModel por meio do conceito de vinculação de dados, que se conecta indiretamente aos dados do modelo. View não precisa ser alterado para qualquer alteração feita em ViewModel. As alterações feitas nos dados em ViewModel são propagadas automaticamente em View devido à vinculação.

Modelo

O modelo são dados de domínio ou objeto de negócios, que contém dados em tempo real. O modelo não carrega comportamentos. O comportamento é implementado principalmente na lógica de negócios.

ViewModel

ViewModel é o local central, onde os dados da lógica de exibição de Model e View são agrupados. ViewModel mantém o estado dinâmico dos dados. Há um fichário implícito entre View e ViewModel para comunicação entre si. Essa associação inclui dados declarativos e associação de comando. A sincronização de View e ViewModel é obtida por meio dessa vinculação. Qualquer mudança feita em View é refletida em ViewModel e, da mesma forma, qualquer mudança em ViewModel é refletida automaticamente em View. A existência desse mecanismo de ligação bidirecional é um aspecto-chave desse padrão MVVM.

KnockoutJS baseia-se nos três conceitos importantes a seguir.

  • Observáveis ​​e rastreamento de dependência entre eles - os elementos DOM são conectados ao ViewModel via 'data-bind'. Eles trocam informações por meio de Observáveis. Isso automaticamente cuida do rastreamento de dependência.

  • Ligações declarativas entre UI e ViewModel - os elementos DOM são conectados a ViewModel por meio do conceito de 'ligação de dados'.

  • Templating para criar componentes reutilizáveis ​​- Templating fornece uma maneira robusta de criar aplicativos da web complexos.

Estudaremos os observáveis ​​neste capítulo.

Como o nome especifica, quando você declara um dado / propriedade de ViewModel como Observável, qualquer modificação de dados a cada vez é refletida automaticamente em todos os locais em que os dados são usados. Isso também inclui a atualização das dependências relacionadas. KO cuida dessas coisas e não há necessidade de escrever código extra para fazer isso.

Usando Observable, torna-se muito fácil fazer a interface do usuário e o ViewModel se comunicarem dinamicamente.

Sintaxe

Você só precisa declarar a propriedade ViewModel com a função ko.observable() para torná-lo observável.

this.property = ko.observable('value');

Exemplo

Vamos dar uma olhada no exemplo a seguir, que demonstra o uso de Observable.

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Observable Example</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js" 
         type = "text/javascript"></script>
   </head>
   
   <body>
      <!-- This is called "view" of HTML markup that defines the appearance of UI -->

      <p>Enter your name: <input data-bind = "value: yourName" /></p>
      <p>Hi <strong data-bind = "text: yourName"></strong> Good Morning!!!</p>

      <script>
         <!-- This is called "viewmodel". This javascript section defines the data and behavior of UI -->

         function AppViewModel() {
            this.yourName = ko.observable("");
         }

         // Activates knockout.js
         ko.applyBindings(new AppViewModel());
      </script>
   </body>
</html>

A linha a seguir é para a caixa de entrada. Como pode ser visto, usamos o atributo data-bind para vincular o valor yourName ao ViewModel.

<p>Enter your name: <input data-bind = "value: yourName" /> <p>

A linha a seguir apenas imprime o valor de yourName. Observe que aqui o tipo de vinculação de dados é o texto, pois estamos simplesmente lendo o valor.

<p>Hi <strong data-bind = "text: yourName"></strong> Good Morning!!!</p>

Na linha a seguir, ko.observable fica de olho na variável yourName para qualquer modificação nos dados. Assim que houver uma modificação, os locais correspondentes também serão atualizados com o valor modificado. Quando você executa o código a seguir, uma caixa de entrada aparecerá. Conforme e quando você atualiza essa caixa de entrada, o novo valor será refletido ou atualizado nos locais onde quer que seja usado.

this.yourName = ko.observable("");

Resultado

Vamos realizar as seguintes etapas para ver como o código acima funciona -

  • Salve o código acima em first_observable_pgm.htm Arquivo.

  • Abra este arquivo HTML em um navegador.

  • Insira o nome como Scott e observe que o nome é refletido na saída.

A modificação de dados pode ocorrer a partir da IU ou de ViewModel. Independentemente de onde os dados são alterados, a IU e o ViewModel mantém a sincronização entre eles. Isso o torna um mecanismo de ligação bidirecional. No exemplo acima, quando você altera seu nome na caixa de entrada, ViewModel obtém um novo valor. Quando você altera a propriedade yourName de dentro de ViewModel, a IU recebe um novo valor.

Ler e escrever observáveis

A tabela a seguir lista as operações de leitura e gravação que podem ser realizadas em Observables.

Sr. Não. Operação de leitura / gravação e sintaxe
1

Read

Para ler o valor basta chamar a propriedade Observable sem parâmetros como: AppViewModel.yourName ();

2

Write

Para escrever / atualizar o valor na propriedade Observable, basta passar o valor desejado no parâmetro como: AppViewModel.yourName ('Bob');

3

Write multiple

Várias propriedades de ViewModel podem ser atualizadas em uma única linha com a ajuda da sintaxe de encadeamento como: AppViewModel.yourName ('Bob'). YourAge (45);

Matrizes Observáveis

A declaração observável cuida das modificações de dados de um único objeto. ObservableArray trabalha com a coleção de objetos. Esse é um recurso muito útil quando você está lidando com aplicativos complexos contendo vários tipos de valores e alterando seu status com frequência com base nas ações do usuário.

Sintaxe

this.arrayName = ko.observableArray();    // It's an empty array

A matriz observável rastreia apenas quais objetos nela são adicionados ou removidos. Ele não notifica se as propriedades do objeto individual são modificadas.

Inicialize pela primeira vez

Você pode inicializar sua matriz e, ao mesmo tempo, declará-la como Observável, passando os valores iniciais para o construtor da seguinte maneira.

this.arrayName = ko.observableArray(['scott','jack']);

Lendo da Matriz Observável

Você pode acessar os elementos da matriz observável da seguinte maneira.

alert('The second element is ' + arrayName()[1]);

Funções ObservableArray

KnockoutJS tem seu próprio conjunto de funções de matriz observável. Eles são convenientes porque -

  • Essas funções funcionam em todos os navegadores.

  • Essas funções cuidarão do rastreamento de dependências automaticamente.

  • A sintaxe é fácil de usar. Por exemplo, para inserir um elemento em uma matriz, você só precisa usar arrayName.push ('valor') em vez de arrayName (). Push ('valor').

A seguir está a lista de vários métodos de Matriz Observável.

Sr. Não. Métodos e Descrição
1 push ('valor')

Insere um novo item no final da matriz.

2 pop ()

Remove o último item da matriz e o retorna.

3 unshift ('valor')

Insere um novo valor no início da matriz.

4 mudança()

Remove o primeiro item da matriz e o retorna.

5 reverter()

Inverte a ordem da matriz.

6 ordenar()

Classifica os itens da matriz em ordem crescente.

7 splice (índice inicial, índice final)

Aceita 2 parâmetros - índice inicial e índice final - remove itens do índice inicial ao final e os retorna como uma matriz.

8 indexOf ('valor')

Esta função retorna o índice da primeira ocorrência do parâmetro fornecido.

9 fatia (índice inicial, índice final)

Este método corta um pedaço de um array. Retorna os itens do índice inicial até o índice final.

10 deletar tudo()

Remove todos os itens e os retorna como uma matriz.

11 remover ('valor')

Remove itens que correspondem ao parâmetro e retorna como uma matriz.

12 remover (função (item) {condição})

Remove itens que satisfazem a condição e os retorna como uma matriz.

13 remover ([conjunto de valores])

Remove itens que correspondem a um determinado conjunto de valores.

14

destroyAll()

Marca todos os itens em uma matriz com propriedade _destroy com valor true.

15

destroy('value')

Procura um item igual ao parâmetro e o marca com uma propriedade especial _destroy com o valor true.

16

destroy(function(item) { condition})

Encontra todos os itens que satisfazem a condição, marca-os com a propriedade _destroy com valor verdadeiro.

17

destroy([set of values])

Encontra os itens que correspondem a um determinado conjunto de valores, marca-os como _destroy com valor verdadeiro.

Note - Funções Destroy e DestroyAll de ObservableArrays são principalmente para desenvolvedores 'Ruby on Rails'.

Quando você usa o método destroy, os itens correspondentes não são realmente excluídos do array naquele momento, mas são ocultados marcando-os com a propriedade _destroy com valor true para que não possam ser lidos pela IU. Os itens marcados como _destroy igual a true são excluídos posteriormente ao lidar com o gráfico de objeto JSON.

Computed Observable é uma função que depende de um ou mais Observables e atualiza automaticamente sempre que seus Observables subjacentes (dependências) mudam.

Os observáveis ​​computados podem ser encadeados.

Sintaxe

this.varName = ko.computed(function(){
   ...
   ... //  function code
   ...
},this);

Exemplo

Vejamos o exemplo a seguir, que demonstra o uso de Observáveis ​​Computados.

<!DOCTYPE html>
   <head >
      <title>KnockoutJS Computed Observables</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js"></script>
   </head>

   <body>
      <p>Enter first number: <input data-bind = "value: a" /></p>
      <p>Enter second number: <input data-bind = "value: b"/></p>
      <p>Average := <span data-bind="text: totalAvg"></span></p>

      <script>
         function MyViewModel() {
            this.a = ko.observable(10);
            this.b = ko.observable(40);

            this.totalAvg = ko.computed(function() {

               if(typeof(this.a()) !== "number" || typeof(this.b()) !== "number") {
                  this.a(Number(this.a()));   //convert string to Number
                  this.b(Number(this.b()));   //convert string to Number
               }

               total = (this.a() + this.b())/2 ;
               return total;
            },this);
         }

         ko.applyBindings(new MyViewModel());
      </script>

   </body>
</html>

Nas linhas a seguir, as duas primeiras são para aceitar valores de entrada. A terceira linha imprime a média desses dois números.

<p>Enter first number: <input data-bind = "value: a" /></p>
<p>Enter second number: <input data-bind = "value: b"/></p>
<p>Average := <span data-bind = "text: totalAvg"></span></p>

Nas linhas a seguir, tipo de Observáveis a e bé o número quando eles são inicializados pela primeira vez dentro de ViewModel. No entanto, em KO, cada entrada aceita da IU está, por padrão, no formato String. Portanto, eles precisam ser convertidos em Número para realizar a operação aritmética neles.

this.totalAvg = ko.computed(function() {
   
   if(typeof(this.a()) !== "number" || typeof(this.b()) !== "number") {
      this.a(Number(this.a()));   //convert string to Number
      this.b(Number(this.b()));   //convert string to Number
   }
   
   total = (this.a() + this.b())/2 ;
   return total;
},this);

Na linha a seguir, a média calculada é exibida na IU. Observe que o tipo de ligação de dados de totalAvg é apenas texto.

<p>Average := <span data-bind = "text: totalAvg"></span></p>

Resultado

Vamos realizar as seguintes etapas para ver como o código acima funciona -

  • Salve o código acima em computed-observable.htm Arquivo.

  • Abra este arquivo HTML em um navegador.

  • Insira quaisquer 2 números nas caixas de texto e observe que a média é calculada.

Gerenciando 'Isto'

Observe que no exemplo acima, o segundo parâmetro é fornecido como thispara função computada. Não é possível referir-se a Observáveisa() e b() sem fornecer this.

Para superar isso, self variável é usada que contém a referência de this. Fazendo isso, não há necessidade de rastrearthisem todo o código. Em vez de,self pode ser usado.

O código ViewModel a seguir foi reescrito para o exemplo acima usando self.

function MyViewModel(){
   self = this;
   self.a = ko.observable(10);
   self.b = ko.observable(40);

   this.totalAvg = ko.computed(function() {
      
      if(typeof(self.a()) !== "number" || typeof(self.b()) !== "number") {
         self.a(Number(self.a()));   //convert string to Number
         self.b(Number(self.b()));   //convert string to Number
      }
      
      total = (self.a() + self.b())/2 ;
      return total;
   });
}

Observáveis ​​Puros Computados

Um Observable Computado deve ser declarado como PureObservável computado se esse Observável estiver simplesmente calculando e retornando o valor e não modificando diretamente os outros objetos ou estado. Pure Computed Observables ajuda Knockout a gerenciar a reavaliação e o uso de memória de forma eficiente.

Notificando assinantes explicitamente

Quando um Computed Observable está retornando um valor de tipo de dados primitivo (String, Boolean, Null e Number), seus assinantes são notificados se e somente se a mudança de valor real ocorrer. Isso significa que se um Observable recebeu o mesmo valor do valor anterior, seus assinantes não são notificados.

Você pode fazer com que os Observáveis ​​Computados sempre notifiquem explicitamente os observadores, mesmo que o novo valor seja igual ao antigo, usando o notify sintaxe a seguir.

myViewModel.property = ko.pureComputed(function() {
   return ...;    // code logic goes here
}).extend({ notify: 'always' });

Limitando notificações de mudança

Muitas atualizações caras podem resultar em problemas de desempenho. Você pode limitar o número de notificações a serem recebidas do Observable usandorateLimit atributo da seguinte forma.

// make sure there are updates no more than once per 100-millisecond period
myViewModel.property.extend({ rateLimit: 100 });

Descobrir se uma propriedade é computável como observável

Em certas situações, pode ser necessário descobrir se uma propriedade é um Observável Computado. As funções a seguir podem ser usadas para identificar os tipos de observáveis.

Sr. Não. Função
1

ko.isComputed

Devoluções true se a propriedade for Computed Observable.

2

ko.isObservable

Devoluções true se a propriedade for Observable, Observable array ou Computed Observable.

3

ko.isWritableObservable

Devoluções truese observável, matriz observável ou observável computado gravável. (Isso também é chamado de ko.isWriteableObservable)

Observáveis ​​computadorizados graváveis

Computed Observable é derivado de um ou vários outros Observables, portanto, é somente leitura. No entanto, é possível tornar o Computed Observable gravável. Para isso, você precisa fornecer uma função de retorno de chamada que funcione em valores escritos.

Esses Observáveis ​​Computados graváveis ​​funcionam exatamente como os Observáveis ​​normais. Além disso, eles exigem que uma lógica personalizada seja construída para interferir nas ações de leitura e gravação.

Pode-se atribuir valores a muitas propriedades observáveis ​​ou observáveis ​​computadas usando a sintaxe de encadeamento da seguinte maneira.

myViewModel.fullName('Tom Smith').age(45)

Exemplo

O exemplo a seguir demonstra o uso de Observável Computável Gravável.

<!DOCTYPE html>
   <head >
      <title>KnockoutJS Writable Computed Observable</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"></script>
   </head>

   <body>
      <p>Enter your birth Date: <input type = "date" data-bind = "value: rawDate" ></p>
      <p><span data-bind = "text: yourAge"></span></p>

      <script>
         function MyViewModel() {
            this.yourAge = ko.observable();
            today = new Date();
            rawDate = ko.observable();

            this.rawDate = ko.pureComputed ({

               read: function() {
                  return this.yourAge;
               },

               write: function(value) {
                  var b = Date.parse(value);    // convert birth date into milliseconds
                  var t = Date.parse(today);    // convert todays date into milliseconds
                  diff = t - b;                 // take difference
                  var y = Math.floor(diff/31449600000);     // difference is converted
                                                            // into years. 31449600000
                                                            //milliseconds form a year.

                  var m = Math.floor((diff % 31449600000)/604800000/4.3);  // calculating
                                                                           // months.
                                                                           // 604800000
                                                                           // milliseconds
                                                                           // form a week.

                  this.yourAge("You are " + y + " year(s) " + m +" months old.");
               },
               owner: this
            });
         }

         ko.applyBindings(new MyViewModel());
      </script>

   </body>
</html>

No código acima, rawDate é a propriedade pureComputed aceita da IU. yourAge Observável é derivado de rawDate.

As datas em JavaScript são manipuladas em milissegundos. Portanto, ambas as datas (data de hoje e data de nascimento) são convertidas em milissegundos e, em seguida, a diferença entre elas é convertida novamente em anos e meses.

Resultado

Vamos realizar as seguintes etapas para ver como o código acima funciona -

  • Salve o código acima em writable_computed_observable.htm Arquivo.

  • Abra este arquivo HTML em um navegador.

  • Insira qualquer data de nascimento e observe que a idade é calculada.

A ligação declarativa em KnockoutJS fornece uma maneira poderosa de conectar dados à IU.

É importante entender a relação entre ligações e observáveis. Tecnicamente, esses dois são diferentes. Você pode usar o objeto JavaScript normal, pois ViewModel e KnockoutJS podem processar a vinculação de View corretamente.

Sem Observable, a propriedade da UI será processada apenas pela primeira vez. Nesse caso, ele não pode ser atualizado automaticamente com base na atualização de dados subjacente. Para conseguir isso, as ligações devem ser referenciadas às propriedades observáveis.

Sintaxe de ligação

A ligação consiste em 2 itens, a ligação name e value. A seguir está um exemplo simples -

Today is : <span data-bind = "text: whatDay"></span>

Aqui, text é o nome da vinculação e whatDay é o valor da vinculação. Você pode ter várias ligações separadas por vírgula, conforme mostrado na sintaxe a seguir.

Your name: <input data-bind = "value: yourName, valueUpdate: 'afterkeydown'" />

Aqui, o valor é atualizado após cada tecla ser pressionada.

Valores Vinculativos

O valor de ligação pode ser um single value, literal, uma variable ou pode ser um JavaScriptexpressão. Se a ligação se referir a alguma expressão ou referência inválida, KO produzirá um erro e interromperá o processamento da ligação.

A seguir estão alguns exemplos de ligações.

<!-- simple text binding -->
<p>Enter employee name: <input   -bind = 'value: empName' /></p>

<!-- click binding, call a specific function -->
<button data-bind="click: sortEmpArray">Sort Array</button>

<!-- options binding -->
<select multiple = "true" size = "8" data-bind = "options: empArray , 
   selectedOptions: chosenItem"> </select>

Observe os seguintes pontos -

  • Espaços em branco não fazem diferença.

  • A partir do KO 3.0, você pode pular o valor de vinculação, o que dará à vinculação um valor indefinido.

Contexto de ligação

Os dados que estão sendo usados ​​nas ligações atuais podem ser referenciados por um objeto. Este objeto é chamadobinding context.

A hierarquia de contexto é criada e gerenciada pelo KnockoutJS automaticamente. A tabela a seguir lista os diferentes tipos de contextos de ligação fornecidos por KO.

Sr. Não. Tipos de contexto de ligação e descrição
1

$root

Isso sempre se refere ao ViewModel de nível superior. Isso torna possível acessar métodos de nível superior para manipular ViewModel. Geralmente é o objeto, que é passado para ko.applyBindings.

2

$data

Esta propriedade é muito parecida com thispalavra-chave no objeto Javascript. A propriedade $ data em um contexto de ligação se refere ao objeto ViewModel para o contexto atual.

3

$index

Esta propriedade contém o índice de um item atual de uma matriz dentro de um loop foreach. O valor de $ index mudará automaticamente conforme e quando a matriz Observable subjacente for atualizada. Obviamente, este contexto está disponível apenas paraforeach ligações.

4

$parent

Esta propriedade se refere ao objeto pai ViewModel. Isso é útil quando você deseja acessar propriedades de ViewModel externas de dentro de um loop aninhado.

5

$parentContext

O objeto de contexto que está vinculado ao nível pai é chamado $parentContext. Isso é diferente de$parent. $ parent se refere aos dados. Enquanto $ parentContext se refere ao contexto de ligação. Por exemplo, você pode precisar acessar o índice de item foreach externo de um contexto interno.

6

$rawdata

Este contexto contém o valor ViewModel bruto na situação atual. Isso se assemelha$data but the difference is, if ViewModel is wrapped in Observable, then $os dados são apenas desembrulhados. ViewModel e $ rawdata tornam-se dados observáveis ​​reais.

7

$component

Este contexto é usado para se referir ao ViewModel desse componente, quando você está dentro de um componente específico. Por exemplo, você pode querer acessar alguma propriedade de ViewModel em vez dos dados atuais na seção de modelo do componente.

8

$componentTemplateNodes

Isso representa uma matriz de nós DOM passados ​​para aquele componente específico quando você está dentro de um modelo de componente específico.

Os termos a seguir também estão disponíveis no contexto vinculativo, mas não são realmente um contexto vinculativo.

  • $context - Isso nada mais é do que um objeto de contexto de ligação existente.

  • $element - Este objeto se refere a um elemento no DOM na ligação atual.

Trabalho com texto e aparências

A seguir está uma lista de tipos de vinculação fornecidos por KO para lidar com texto e aparências visuais.

Sr. Não. Tipo de ligação e uso
1 visível:

Para mostrar ou ocultar o elemento HTML DOM dependendo de certas condições.

2 texto:

Para definir o conteúdo de um elemento HTML DOM.

3 html:

Para definir o conteúdo da marcação HTML de um elemento DOM.

4 css:

Para aplicar classes CSS a um elemento.

5 estilo:

Para definir o atributo de estilo embutido de um elemento.

6 attr:

Para adicionar atributos a um elemento dinamicamente.

Trabalhando com Ligações de Fluxo de Controle

A seguir está uma lista de tipos de vinculação de fluxo de controle fornecida por KO.

Sr. Não. Tipo de ligação e uso
1 foreach:

Nessa associação, cada item da matriz é referenciado na marcação HTML em um loop.

2 if:

Se a condição for verdadeira, a marcação HTML fornecida será processada. Caso contrário, será removido do DOM.

3 ifnot:

Negação de If. Se a condição for verdadeira, a marcação HTML fornecida será processada. Caso contrário, será removido do DOM.

4 com:

Essa vinculação é usada para vincular os elementos filhos de um objeto no contexto do objeto especificado.

5 componente: OU componente:

Essa ligação é usada para inserir um componente em elementos DOM e passar os parâmetros opcionalmente.

Trabalho com vinculações de campos de formulário

A seguir está a lista de tipos de vinculação de campos de formulário fornecidos por KO.

Sr. Não. Tipo de ligação e uso
1 clique:

Essa ligação é usada para invocar uma função JavaScript associada a um elemento DOM com base em um clique.

2 evento:

Essa ligação é usada para ouvir os eventos DOM especificados e chamar funções de manipulador associadas com base neles.

3 enviar:

Essa ligação é usada para invocar uma função JavaScript quando o elemento DOM associado é enviado.

4 habilitar:

Essa associação é usada para habilitar certos elementos DOM com base em uma condição especificada.

5 desativar:

Essa ligação desativa o elemento DOM associado quando o parâmetro é avaliado como verdadeiro.

6 valor:

Essa ligação é usada para vincular o valor do respectivo elemento DOM à propriedade ViewModel.

7 textInput:

Essa associação é usada para criar uma associação bidirecional entre a caixa de texto ou textarea e a propriedade ViewModel.

8 hasFocus:

Essa ligação é usada para definir manualmente o foco de um elemento HTML DOM por meio de uma propriedade ViewModel.

9 verificado:

Essa ligação é usada para criar um link entre um elemento de formulário verificável e a propriedade ViewModel.

10 opções:

Essa ligação é usada para definir as opções para um elemento selecionado.

11 selectedOptions:

Essa ligação é usada para trabalhar com elementos que são selecionados atualmente no controle de formulário de seleção de várias listas.

12 UniqueName:

Essa ligação é usada para gerar um nome exclusivo para um elemento DOM.

KnockoutJs rastreia automaticamente as dependências quando os valores são atualizados. Ele tem um único objeto chamadodependency tracker (ko.dependencyDetection) que atua como um intermediário entre as duas partes para assinar as dependências.

A seguir está o algoritmo para rastreamento de dependência.

Step 1 - Sempre que você declara um observável calculado, KO invoca imediatamente sua função de avaliador para obter seu valor inicial.

Step 2- A assinatura é configurada para qualquer observável que o avaliador lê. Em um aplicativo, as assinaturas antigas que não são mais usadas são descartadas.

Step 3 - KO finalmente notifica o observável calculado atualizado.

Example

<!DOCTYPE html>
<html>
   <head>
      <title>KnockoutJS How Dependency Tracking Works</title>
      <!-- CDN's-->
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js"
         type = "text/javascript"></script>
   </head>
   
   <body>
      <div>
         <form data-bind = "submit: addFruits">
            <b>Add Fruits:</b>
            <input data-bind = 'value: fruitToAdd, valueUpdate: "afterkeydown"'/>
            <button type = "submit" data-bind = "enable: fruitToAdd().length > 0">Add</button>
            <p><b>Your fruits list:</b></p>
            <select multiple = "multiple" width = "50" data-bind = "options: fruits"> </select>
         </form>
      </div>
      
      <script>
         var Addfruit = function(fruits) {
            this.fruits = ko.observableArray(fruits);
            this.fruitToAdd = ko.observable("");
            
            this.addFruits = function() {
               
               if (this.fruitToAdd() != "") {
                  this.fruits.push(this.fruitToAdd());   // Adds a fruit
                  this.fruitToAdd("");                   // Clears the text box
               }
                
            }.bind(this);                                // "this" is the view model
         };

         ko.applyBindings(new Addfruit(["Apple", "Orange", "Banana"]));
      </script>
      
   </body>
</html>

Output

Vamos realizar as seguintes etapas para ver como o código acima funciona -

  • Salve o código acima em dependency_tracking.htm Arquivo.

  • Abra este arquivo HTML em um navegador.

  • Insira qualquer nome de fruta e clique no botão Adicionar.

Controlando dependências usando Peek

O Computed Observable pode ser acessado sem criar uma dependência, usando o peekfunção. Ele controla o Observable atualizando a propriedade computada.

Example

<!DOCTYPE html>
<html>
   <head>
      <title>KnockoutJs Controlling Dependencies Using Peek</title>
      <!-- CDN's-->
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js"
         type = "text/javascript"></script>
   </head>
   
   <body>
      <div class = "logblock">
         <h3>Computed Log</h3>
         <pre class = "log" data-bind = "html: computedLog"></pre>
      </div>

      <script>
         function AppData() {
            this.firstName = ko.observable('John');
            this.lastName = ko.observable('Burns');
            this.computedLog = ko.observable('Log: ');
            
            this.fullName = ko.computed(function () {
               var value = this.firstName() + " " + this.lastName();
               this.computedLog(this.computedLog.peek() + value + '; <br/>');
               return value;
            }, this);

            this.step = ko.observable(0);
            this.next = function () {
               this.step(this.step() === 2 ? 0 : this.step()+1);
            };
         };
         
         ko.applyBindings(new AppData());
      </script>
      
   </body>
</html>

Output

Vamos realizar as seguintes etapas para ver como o código acima funciona -

  • Salve o código acima em dependency_tracking_peek.htm Arquivo.

  • Abra este arquivo HTML em um navegador.

Observações

Ignorando dependências dentro de uma dependência computada

o ko.ignoreDependenciesA função ajuda a ignorar as dependências que você não deseja rastrear nas dependências calculadas. A seguir está sua sintaxe.

ko.ignoreDependencies( callback, callbackTarget, callbackArgs );

Por que dependências circulares não são significativas

Se KO estiver avaliando um Observável Computado, ele não reiniciará uma avaliação do Observável Computado dependente. Portanto, não faz sentido incluir ciclos em suas cadeias de dependência.

Templateé um conjunto de elementos DOM que podem ser usados ​​repetidamente. A modelagem facilita a construção de aplicativos complexos devido à sua propriedade de minimizar a duplicação de elementos DOM.

Existem 2 maneiras de criar modelos.

  • Native templating- Este método oferece suporte às ligações de fluxo de controle, como foreach, with e if. Essas ligações capturam a marcação HTML existente no elemento e a usam como modelo para itens aleatórios. Nenhuma biblioteca externa é necessária para este modelo.

  • String-based templating- KO se conecta ao mecanismo de terceiros para passar valores de ViewModel para ele e injeta a marcação resultante no documento. Por exemplo, JQuery.tmpl e Underscore Engine.

Syntax

template: <parameter-value>

<script type = "text/html" id = "template-name">
   ...
   ...   // DOM elemets to be processed
   ...
</script>

Observe que type é fornecido como text/html no bloco de script para notificar KO de que não é um bloco executável, mas apenas um bloco de modelo que precisa ser renderizado.

Parameters

A combinação das seguintes propriedades pode ser enviada como valor de parâmetro para o modelo.

  • name - Isso representa o nome do modelo.

  • nodes- Isso representa uma matriz de nós DOM a serem usados ​​como o modelo. Este parâmetro é ignorado se o parâmetro de nome for passado.

  • data - Isso nada mais é do que dados a serem mostrados por meio do modelo.

  • if - O modelo será veiculado se a condição fornecida resultar em um valor verdadeiro ou semelhante a verdadeiro.

  • foreach - Para servir o modelo em formato foreach.

  • as - Isso é apenas para criar um alias no elemento foreach.

  • afterAdd, afterRender, beforeRemove - Tudo para representar funções que podem ser chamadas a serem executadas dependendo da operação realizada.

Observações

Renderizando um Template nomeado

Os modelos são definidos implicitamente pela marcação HTML dentro do DOM quando usados ​​com associações de fluxo de controle. No entanto, se desejar, você pode fatorar os modelos em um elemento separado e, em seguida, referenciá-los pelo nome.

Example

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Templating - Named Template</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"
         type = "text/javascript"></script>
   </head>

   <body>
      <h2>Friends List</h2>
      Here are the Friends from your contact page:
      <div data-bind = "template: { name: 'friend-template', data: friend1 }"></div>
      <div data-bind = "template: { name: 'friend-template', data: friend2 }"></div>

      <script type = "text/html" id = "friend-template">
         <h3 data-bind = "text: name"></h3>
         <p>Contact Number: <span data-bind = "text: contactNumber"></span></p>
         <p>Email-id: <span data-bind = "text: email"></span></p>
      </script>

      <script type = "text/javascript">
         function MyViewModel() {
            this.friend1 = { 
               name: 'Smith', 
               contactNumber: 4556750345, 
               email: '[email protected]' 
            };
            
            this.friend2 = { 
               name: 'Jack', 
               contactNumber: 6789358001, 
               email: '[email protected]' 
            };
         }

         var vm = new MyViewModel();
         ko.applyBindings(vm);
      </script>
      
   </body>
</html>

Output

Vamos realizar as seguintes etapas para ver como o código acima funciona -

  • Salve o código acima em template-named.htm Arquivo.

  • Abra este arquivo HTML em um navegador.

  • Aqui, o modelo de amigo é usado 2 vezes.

Usando "foreach" no modelo

A seguir está um exemplo de uso foreach parâmetro junto com o nome do modelo.

Example

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Templating - foreach used with Template</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"
         type = "text/javascript"></script>
   </head>

   <body>
      <h2>Friends List</h2>
      Here are the Friends from your contact page:
      <div data-bind = "template: { name: 'friend-template', foreach: friends }"></div>

      <script type = "text/html" id = "friend-template">
         <h3 data-bind = "text: name"></h3>
         <p>Contact Number: <span data-bind = "text: contactNumber"></span></p>
         <p>Email-id: <span data-bind = "text: email"></span></p>
      </script>

      <script type = "text/javascript">
         function MyViewModel() {
            this.friends = [
               { name: 'Smith', contactNumber: 4556750345, email: '[email protected]' },
               { name: 'Jack', contactNumber: 6789358001, email: '[email protected]' },
               { name: 'Lisa', contactNumber: 4567893131, email: '[email protected]' }
            ]
         }

         var vm = new MyViewModel();
         ko.applyBindings(vm);
      </script>
      
   </body>
</html>

Output

Vamos realizar as seguintes etapas para ver como o código acima funciona -

  • Salve o código acima em template-foreach.htm Arquivo.

  • Abra este arquivo HTML em um navegador.

  • Aqui, o controle foreach é usado na vinculação do modelo.

Criação de alias usando como palavra-chave para itens foreach

Veja a seguir como um alias pode ser criado para um item foreach -

<div data-bind = "template: { 
   name: 'friend-template', 
   foreach: friends, 
   as: 'frnz' 
}"></div>

Torna-se fácil referir-se a objetos pais de dentro de loops foreach criando um alias. Esse recurso é útil quando o código é complexo e aninhado em vários níveis.

Example

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Templating - using alias in Template</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"
         type = "text/javascript"></script>
   </head>

   <body>
      <h2>Friends List</h2>
      Here are the Friends from your contact page:
      <ul data-bind = "template: { 
         name: 'friend-template', 
         foreach: friends, 
         as: 'frnz' 
      }"></ul>

      <script type = "text/html" id = "friend-template">
         <li>
            <h3 data-bind = "text: name"></h3>
            <span>Contact Numbers</span>
            <ul data-bind = "template: { 
               name : 'contacts-template', 
               foreach:contactNumber, 
               as: 'cont'
            } "></ul>
            <p>Email-id: <span data-bind = "text: email"></span></p>
         </li>
      </script>

      <script type = "text/html" id = "contacts-template">
         <li>
            <p><span data-bind = "text: cont"></span></p>
         </li>
      </script>

      <script type = "text/javascript">
         function MyViewModel() {
            this.friends = ko.observableArray ( [
               { 
                  name: 'Smith', 
                  contactNumber: [ 4556750345, 4356787934 ], 
                  email: '[email protected]' 
               },
               
               { 
                  name: 'Jack', 
                  contactNumber: [ 6789358001, 3456895445 ], 
                  email: '[email protected]' 
               },
               
               { 
                  name: 'Lisa', 
                  contactNumber: [ 4567893131, 9876456783, 1349873445 ],  
                  email: '[email protected]' 
               }
            ]);
         }

         var vm = new MyViewModel();
         ko.applyBindings(vm);
      </script>
      
   </body>
</html>

Output

Vamos realizar as seguintes etapas para ver como o código acima funciona -

  • Salve o código acima em template-as-alias.htm Arquivo.

  • Abra este arquivo HTML em um navegador.

  • Alias ​​é usado em vez do nome completo dos arrays.

Usando afterAdd, beforeRemove e afterRender

Existem situações em que a lógica customizada extra precisa ser executada em elementos DOM criados pelo modelo. Nesse caso, os seguintes retornos de chamada podem ser usados. Considere que você está usando o elemento foreach, então -

afterAdd - Esta função é chamada quando um novo item é adicionado ao array mencionado em foreach.

beforeRemove - Esta função é chamada antes de remover o item de uma matriz mencionada em foreach.

afterRender - A função mencionada aqui é invocada sempre que foreach é renderizado e novas entradas são adicionadas ao array.

Example

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Templating - Use of afterRender Template</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"
         type = "text/javascript"></script>
      <script src = "https://code.jquery.com/jquery-2.1.3.min.js"
         type = "text/javascript"></script>
   </head>

   <body>
      <h2>Friends List</h2>
      Here are the Friends from your contact page:
      <div data-bind = "template: { 
         name: 'friend-template', 
         foreach: friends , 
         afterRender: afterProcess
      }"></div>

      <script type = "text/html" id = "friend-template">
         <h3 data-bind = "text: name"></h3>
         <p>Contact Number: <span data-bind = "text: contactNumber"></span></p>
         <p>Email-id: <span data-bind = "text: email"></span></p>
         <button data-bind = "click: $root.removeContact">remove </button>
      </script>

      <script type = "text/javascript">
         function MyViewModel() {
            self = this;
            this.friends = ko.observableArray ([
               { name: 'Smith', contactNumber: 4556750345, email: '[email protected]' },
               { name: 'Jack', contactNumber: 6789358001, email: '[email protected]' },
            ])

            this.afterProcess = function(elements, data){
               $(elements).css({color: 'magenta' });
            }

            self.removeContact = function() {
               self.friends.remove(this);
            }
         }

         var vm = new MyViewModel();
         ko.applyBindings(vm);
      </script>
   </body>
</html>

Output

Vamos realizar as seguintes etapas para ver como o código acima funciona -

  • Salve o código acima em template-afterrender.htm Arquivo.

  • Abra este arquivo HTML em um navegador.

  • Aqui, a função afterProcess é executada sempre que foreach é renderizado.

Escolhendo o modelo dinamicamente

Se houver vários modelos disponíveis, um pode ser escolhido dinamicamente tornando o nome observableparâmetro. Portanto, o valor do modelo será reavaliado conforme o parâmetro de nome muda e, por sua vez, os dados são renderizados novamente.

Example

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Templating - Dynamic Template</title>
      <script src = "https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"
         type = "text/javascript"></script>
   </head>
   
   <body>
      <h2>Friends List</h2>
      Here are the Friends from your contact page:
      <div data-bind = "template: { 
         name: whichTemplate, 
         foreach: friends 
      }"></div>

      <script type = "text/html" id = "only-phon">
         <h3 data-bind = "text: name"></h3>
         <p>Contact Number: <span data-bind = "text: contactNumber"></span></p>
      </script>

      <script type = "text/html" id = "only-email">
         <h3 data-bind = "text: name"></h3>
         <p>Email-id: <span data-bind = "text: email"></span></p>
      </script>

      <script type = "text/javascript">
         function MyViewModel() {
   
            this.friends = ko.observableArray ([
               {
                  name: 'Smith', 
                  contactNumber: 4556750345, 
                  email: '[email protected]', 
                  active: ko.observable(true)
               },
               
               {
                  name: 'Jack', 
                  contactNumber: 6789358001, 
                  email: '[email protected]', 
                  active: ko.observable(false)
               },
            ]);

            this.whichTemplate = function(friends) {
               return friends.active() ? "only-phon" : "only-email";
            }
         }

         var vm = new MyViewModel();
         ko.applyBindings(vm);
      </script>
      
   </body>
</html>

Output

Vamos realizar as seguintes etapas para ver como o código acima funciona -

  • Salve o código acima em template-dynamic.htm Arquivo.

  • Abra este arquivo HTML em um navegador.

  • O modelo a ser usado é decidido de acordo com o valor do sinalizador ativo.

Usando motores externos baseados em string

A modelagem nativa funciona perfeitamente com vários elementos de fluxo de controle, mesmo com blocos de código aninhados. O KO também oferece uma maneira de integração com a biblioteca de modelos externa, como o Underscore templating Engine ou JQuery.tmpl.

Conforme mencionado no site oficial, JQuery.tmpl não está mais em desenvolvimento ativo desde dezembro de 2011. Portanto, o modelo nativo KO é recomendado apenas em vez de JQuery.tmpl ou qualquer outro mecanismo de modelo baseado em string.

Por favor, consulte o site oficial para mais detalhes sobre isso.

Os componentes são uma ótima maneira de organizar o código da IU para estruturar um grande aplicativo e promover a reutilização do código.

Ele é herdado ou aninhado de outro componente. Para carregamento e configuração, ele define suas próprias convenções ou lógica.

Ele é empacotado para ser reutilizado em todo o aplicativo ou projeto. Representa as seções completas do aplicativo ou pequenos controles / widgets. Ele pode ser carregado ou pré-carregado sob demanda.

Registro de Componente

Os componentes podem ser registrados usando o ko.components.register()API. Ajuda a carregar e representar os componentes em KO. O nome do componente com a configuração é esperado para registro. A configuração especifica como determinar o viewModel e o modelo.

Syntax

Os componentes podem ser registrados da seguinte forma -

ko.components.register('component-name', {
   viewModel: {...},    //function code
   template: {....)	//function code
});
  • o component-name pode ser qualquer string não vazia.

  • viewModel é opcional e pode assumir qualquer um dos formatos de viewModel listados nas próximas seções.

  • template é obrigatório e pode assumir qualquer um dos formatos de modelo listados nas próximas seções.

Declarando um ViewModel

A tabela a seguir lista os formatos de viewModel que podem ser usados ​​para registrar os componentes.

Sr. Não. Formulários e descrição do viewModel
1

constructor function

Ele cria um objeto viewModel separado para cada componente. O objeto ou função é usado para vincular na visualização de componentes.

function SomeComponentViewModel(params) {
   this.someProperty = params.something;
}
ko.components.register('component name', {
   viewModel: SomeComponentViewModel,
   template: ...
});
2

shared object instance

A instância do objeto viewModel é compartilhada. A propriedade da instância é passada para usar o objeto diretamente.

var sharedViewModelInstance = { ... };

ko.components.register('component name', {
   viewModel: { instance: sharedViewModelInstance },
   template: ...
});
3

createViewModel

Ele chama uma função que atua como uma fábrica e pode ser usada como modelo de visualização que pode retornar um objeto.

ko.components.register('component name', {  
   viewModel: {  
      createViewModel: function (params, componentInfo) {  
         ...       //function code  
         ...
      }  
   },  
   template: ....  
});
4

AMD module

É um formato de módulo para definir módulos em que o módulo e as dependências são carregados de forma assíncrona.

ko.components.register('component name', {
   viewModel: { require: 'some/module/name' },
   template: ...
});

define(['knockout'], function(ko) {
   function MyViewModel() {
      // ...
   }

   return MyViewModel;
});

Declarando um modelo

A tabela a seguir lista os formatos de modelo que podem ser usados ​​para registrar os componentes.

Sr. Não. Formulários de modelo
1

element ID

ko.components.register('component name', {
   template: { element: 'component-template' },
   viewModel: ...
});
2

element instance

var elemInstance = document.getElementById('component-template');

ko.components.register('component name', {
   template: { element: elemInstance },
   viewModel: ...
});
3

string of markup

ko.components.register('component name', {
   template: '<input data-bind = "value: yourName" />\
      <button data-bind = "click: addEmp">Add Emp </button>',
   viewModel: ...
});
4

DOM nodes

var emp = [
   document.getElementById('node 1'),
   document.getElementById('node 2'),
];

ko.components.register('component name', {
   template: emp,
   viewModel: ...
});
5

document fragement

ko.components.register('component name', {
   template: someDocumentFragmentInstance,
   viewModel: ...
});
6

AMD module

ko.components.register('component name', {
   template: { require: 'some/template' },
   viewModel: ...
});

Componentes registrados como um único módulo AMD

O módulo AMD pode registrar um componente sozinho sem usar o par viewModel / template.

ko.components.register('component name',{ require: 'some/module'});

Vinculação de componente

Existem duas formas de vinculação de componentes.

  • Full syntax- Passa o parâmetro e o objeto para o componente. Ele pode passar usando as seguintes propriedades.

    • name - Adiciona o nome do componente.

    • params - Pode passar vários parâmetros em objeto no componente.

<div data-bind='component: {
   name: "tutorials point",
   params: { mode: "detailed-list", items: productsList }
}'>
</div>
  • Shorthand syntax - Ele passa a string como um nome de componente e não inclui o parâmetro nele.

<div data-bind = 'component: "component name"'></div>
  • Template-only components - Os componentes só podem definir o modelo sem especificar o viewModel.

ko.components.register('component name', {
   template:'<input data-bind = "value: someName" />,
});
  • Using Component without a container element- Os componentes podem ser usados ​​sem o uso de elemento de contêiner extra. Isso pode ser feito usandocontainerless flow controle que é semelhante à tag de comentário.

<!--ko.component: ""-->
<!--/ko-->

Elemento Personalizado

O elemento personalizado é uma forma de renderizar um componente. Aqui, você pode escrever diretamente um nome de elemento de marcação auto-descritivo em vez de definir um espaço reservado, onde os componentes são vinculados a ele.

<products-list params = "name: userName, type: userType"></products-list>

Parâmetro de passagem

paramsatributo é usado para passar o parâmetro para o componente viewModel. É semelhante ao atributo de ligação de dados. O conteúdo do atributo params é interpretado como um literal de objeto JavaScript (assim como um atributo data-bind), então você pode passar valores arbitrários de qualquer tipo. Ele pode passar o parâmetro das seguintes maneiras -

  • Communication between parent and child components- O componente não é instanciado por si mesmo, então as propriedades do viewmodel são referenciadas de fora do componente e, portanto, seriam recebidas pelo viewmodel do componente filho. Por exemplo, você pode ver na sintaxe a seguir queModelValue é o viewmodel pai, que é recebido pelo construtor viewModel filho ModelProperty.

  • Passing observable expressions - Possui três valores no parâmetro params.

    • simpleExpression- É um valor numérico. Não envolve quaisquer observáveis.

    • simpleObservable- É uma instância definida no viewModel pai. O viewModel pai obterá automaticamente as alterações no observável feitas pelo viewModel filho.

    • observableExpression- Expression lê o observável quando a expressão é avaliada por si mesma. Quando o valor observável muda, o resultado da expressão também pode mudar com o tempo.

Podemos passar os parâmetros da seguinte forma -

<some-component
   params = 'simpleExpression: 1 + 1,
      simpleObservable: myObservable,
      observableExpression: myObservable() + 1'>
</some-component>

Podemos passar os parâmetros em viewModel da seguinte maneira -

<some-component
   params = 'objectValue:{a: 3, b: 2},
      dateValue: new date(),
      stringValue: "Hi",
      numericValue:123,
      boolValue: true/false,
      ModelProperty: ModelValue'>
</some-component>

Passando marcação para componentes

A marcação recebida é usada para criar um componente e é selecionada como parte da saída. Os nós a seguir são passados ​​como parte da saída no modelo de componente.

template: { nodes: $componentTemplateNodes }

Controle de nomes de tag de elemento personalizado

Os nomes que você registra nos componentes usando ko.components.register, o mesmo nome corresponde aos nomes de tag do elemento personalizado. Podemos alterar os nomes de tag do elemento personalizado, substituindo-o para controlar usandogetComponentNameForNode.

ko.components.getComponentNameForNode = function(node) {
   ...
   ...   //function code
   ...
}

Registro de elementos personalizados

Os elementos personalizados podem ser disponibilizados imediatamente, se o carregador de componente padrão for usado e, portanto, o componente for registrado usando ko.components.register. Se não estivermos usando oko.components.registere implementar o carregador de componente personalizado, o elemento personalizado pode ser usado definindo qualquer nome de elemento de sua escolha. Não há necessidade de especificar a configuração quando você estiver usandoko.components.register já que o carregador de componente personalizado não o usa mais.

ko.components.register('custom-element', { ......... });

Example

<!DOCTYPE html>
   <head>
      <title>KnockoutJS Components</title>
      <script src = "https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
      <script src = "https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
   </head>
   
   <body>
      <!--params attribute is used to pass the parameter to component viewModel.-->
      <click params = "a: a, b: b"></click>

      <!--template is used for a component by specifying its ID -->
      <template id = "click-l">
         <div data-bind = "text: a"></div>

         <!--Use data-bind attribute to bind click:function() to ViewModel. -->
         <button data-bind = "click:function(){callback(1)}">Increase</button>
         <button data-bind = "click:function(){callback(-1)}">Decrease</button>
      </template>

      <script>
         //Here components are registered
         ko.components.register('click', {
            
            viewModel: function(params) {
               self = this;
               this.a = params.a;
               this.b = params.b;

               this.callback = function(num) {
                  self.b(parseInt(num));
                  self.a( self.a() + parseInt(num) );
               };
            },
            template: { element: 'click-l' }
         });

         //keeps an eye on variable for any modification in data
         function viewModel() {
            this.a = ko.observable(2);
            this.b = ko.observable(0);
         }

         ko.applyBindings(new viewModel() );
      </script>
      
   </body>
</html>

Output

Vamos realizar as seguintes etapas para ver como o código acima funciona -

  • Salve o código acima em component_register.htm Arquivo.

  • Abra este arquivo HTML em um navegador.

Carregadores de componentes

Os carregadores de componentes são usados ​​para passar o par template / viewModel de forma assíncrona para o nome de componente fornecido.

O carregador de componente padrão

O carregador de componente padrão depende da configuração registrada explicitamente. Cada componente é registrado antes de usar o componente.

ko.components.defaultLoader

Funções de utilitário do carregador de componentes

O carregador de componente padrão pode ler e gravar usando as seguintes funções.

Sr. Não. Funções utilitárias e descrição
1

ko.components.register(name, configuration)

O componente está registrado.

2

ko.components.isRegistered(name)

Se o nome do componente específico já estiver registrado, ele retornará como verdadeiro, caso contrário, será falso.

3

ko.components.unregister(name)

O nome do componente é removido do registro.

4

ko.components.get(name, callback)

Essa função vai passo a passo para cada carregador registrado para encontrar quem passou a definição viewModel / template para o nome do componente como primeiro. Em seguida, ele retorna a declaração viewModel / template invocandocallback. Se o carregador registrado não puder encontrar nada sobre o componente, ele invocacallback(null).

5

ko.components.clearCachedDefinition(name)

Esta função pode ser chamada quando queremos limpar a entrada de cache de componente fornecida. Se o componente for necessário na próxima vez, novamente os carregadores serão consultados.

Implementando um carregador de componente personalizado

O carregador de componente personalizado pode ser implementado das seguintes maneiras -

  • getConfig(name, callback)- Dependendo dos nomes, podemos passar as configurações de forma programática. Podemos chamar o callback (componentConfig) para passar as configurações, onde o objeto componentConfig pode ser usado pelo loadComponent ou qualquer outro loader.

  • loadComponent(name, componentConfig, callback)- Esta função resolve o viewModel e a parte do template da configuração, dependendo da forma como está configurado. Podemos chamar o callback (resultado) para passar o par viewmodel / template, onde o resultado do objeto é definido pelas seguintes propriedades.

    • template- Obrigatório. Retorna a matriz de nós DOM.

    • createViewModel(params, componentInfo)- Opcional. Retorna o objeto viewModel, dependendo de como a propriedade viewModel foi configurada.

  • loadTemplate(name, templateConfig, callback)- Os nós DOM são passados ​​em um modelo usando lógica personalizada. O objeto templateConfig é uma propriedade do template de um objeto componentConfig. callback (domNodeArray) é chamado para passar uma matriz de nós DOM.

  • loadViewModel(name, templateConfig, callback) - viewModel factory é passado em uma configuração viewModel usando lógica customizada.