KnockoutJS - Componentes

Los componentes son una gran forma de organizar el código de la interfaz de usuario para estructurar una aplicación grande y promover la reutilización del código.

Se hereda o anida de otro componente. Para la carga y configuración, define sus propias convenciones o lógica.

Está empaquetado para reutilizarse en toda la aplicación o el proyecto. Representa las secciones completas de la aplicación o pequeños controles / widgets. Se puede cargar o precargar a pedido.

Registro de componentes

Los componentes pueden registrarse usando el ko.components.register()API. Ayuda a cargar y representar los componentes en KO. Se espera el nombre del componente con la configuración para el registro. La configuración especifica cómo determinar el viewModel y la plantilla.

Syntax

Los componentes se pueden registrar de la siguiente manera:

ko.components.register('component-name', {
   viewModel: {...},    //function code
   template: {....)	//function code
});
  • los component-name puede ser cualquier cadena no vacía.

  • viewModel es opcional y puede tomar cualquiera de los formatos viewModel listados en las siguientes secciones.

  • template es obligatorio y puede tomar cualquiera de los formatos de plantilla que se enumeran en las siguientes secciones.

Indicar un modelo de vista

La siguiente tabla enumera los formatos viewModel que se pueden usar para registrar los componentes.

No Señor. viewModel Formularios y descripción
1

constructor function

Crea un objeto viewModel separado para cada componente. El objeto o función se utiliza para enlazar en la vista de componentes.

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

shared object instance

La instancia del objeto viewModel se comparte. La propiedad de la instancia se pasa para usar el objeto directamente.

var sharedViewModelInstance = { ... };

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

createViewModel

Llama a una función que actúa como una fábrica y se puede usar como modelo de vista que puede devolver un objeto.

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

AMD module

Es un formato de módulo para definir módulos donde el módulo y las dependencias se cargan de forma asincrónica.

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

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

   return MyViewModel;
});

Indicar una plantilla

La siguiente tabla enumera los formatos de plantilla que se pueden utilizar para registrar los componentes.

No Señor. Formularios de plantilla
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 un solo módulo AMD

El módulo AMD puede registrar un componente por sí mismo sin utilizar el par viewModel / template.

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

Enlace de componentes

Hay dos formas de vincular componentes.

  • Full syntax- Pasa el parámetro y el objeto al componente. Puede pasar usando las siguientes propiedades.

    • name - Agrega el nombre del componente.

    • params - Puede pasar múltiples parámetros en el objeto del componente.

<div data-bind='component: {
   name: "tutorials point",
   params: { mode: "detailed-list", items: productsList }
}'>
</div>
  • Shorthand syntax - Pasa la cadena como nombre de componente y no incluye parámetro en ella.

<div data-bind = 'component: "component name"'></div>
  • Template-only components - Los componentes solo pueden definir la plantilla sin especificar viewModel.

ko.components.register('component name', {
   template:'<input data-bind = "value: someName" />,
});
  • Using Component without a container element- Los componentes se pueden utilizar sin utilizar un elemento contenedor adicional. Esto se puede hacer usandocontainerless flow control que es similar a la etiqueta de comentario.

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

Elemento personalizado

El elemento personalizado es una forma de renderizar un componente. Aquí, puede escribir directamente un nombre de elemento de marcado autodescriptivo en lugar de definir un marcador de posición, donde los componentes se enlazan a través de él.

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

Paso de parámetro

paramsEl atributo se usa para pasar el parámetro al componente viewModel. Es similar al atributo de enlace de datos. El contenido del atributo params se interpreta como un objeto literal de JavaScript (como un atributo de enlace de datos), por lo que puede pasar valores arbitrarios de cualquier tipo. Puede pasar el parámetro de las siguientes formas:

  • Communication between parent and child components- El componente no se instancia por sí mismo, por lo que las propiedades del modelo de vista se refieren desde fuera del componente y, por lo tanto, el modelo de vista del componente secundario las recibiría. Por ejemplo, puede ver en la siguiente sintaxis queModelValue es el modelo de vista principal, que recibe el constructor de modelo de vista secundario ModelProperty.

  • Passing observable expressions - Tiene tres valores en el parámetro params.

    • simpleExpression- Es un valor numérico. No involucra ningún observable.

    • simpleObservable- Es una instancia que se define en el modelo de vista principal. El viewModel principal obtendrá automáticamente los cambios en el observable realizado por el viewModel secundario.

    • observableExpression- La expresión lee el observable cuando la expresión se evalúa por sí misma. Cuando cambia el valor observable, el resultado de la expresión también puede cambiar con el tiempo.

Podemos pasar los parámetros de la siguiente manera:

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

Podemos pasar los parámetros en viewModel de la siguiente manera:

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

Pasar el marcado a los componentes

El marcado recibido se utiliza para crear un componente y se selecciona como parte de la salida. Los siguientes nodos se pasan como parte de la salida en la plantilla del componente.

template: { nodes: $componentTemplateNodes }

Control de nombres de etiquetas de elementos personalizados

Los nombres que registra en los componentes utilizando ko.components.register, el mismo nombre corresponde a los nombres de las etiquetas de elementos personalizados. Podemos cambiar los nombres de las etiquetas de los elementos personalizados anulándolos para controlar usandogetComponentNameForNode.

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

Registro de elementos personalizados

Los elementos personalizados pueden estar disponibles inmediatamente, si se usa el cargador de componentes predeterminado y, por lo tanto, el componente se registra usando ko.components.register. Si no estamos usando elko.components.registere implementando el cargador de componentes personalizados, entonces el elemento personalizado se puede usar definiendo cualquier nombre de elemento de su elección. No es necesario especificar la configuración cuando está utilizandoko.components.register ya que el cargador de componentes personalizados ya no lo usa.

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

Realicemos los siguientes pasos para ver cómo funciona el código anterior:

  • Guarde el código anterior en component_register.htm archivo.

  • Abra este archivo HTML en un navegador.

Cargadores de componentes

Los cargadores de componentes se utilizan para pasar el par plantilla / viewModel de forma asincrónica para el nombre de componente dado.

El cargador de componentes predeterminado

El cargador de componentes predeterminado depende de la configuración registrada explícitamente. Cada componente se registra antes de usar el componente.

ko.components.defaultLoader

Funciones de la utilidad del cargador de componentes

El cargador de componentes predeterminado puede leer y escribir utilizando las siguientes funciones.

No Señor. Funciones de utilidad y descripción
1

ko.components.register(name, configuration)

El componente está registrado.

2

ko.components.isRegistered(name)

Si el nombre del componente en particular ya está registrado, devuelve verdadero o falso.

3

ko.components.unregister(name)

El nombre del componente se elimina del registro.

4

ko.components.get(name, callback)

Esta función va paso a paso a cada cargador registrado para encontrar quién ha pasado primero la definición de viewModel / template para el nombre del componente. Luego devuelve la declaración viewModel / template invocandocallback. Si el cargador registrado no pudo encontrar nada sobre el componente, entonces invocacallback(null).

5

ko.components.clearCachedDefinition(name)

Se puede llamar a esta función cuando queremos borrar la entrada de caché del componente dado. Si el componente es necesario la próxima vez, se consultará nuevamente a los cargadores.

Implementación de un cargador de componentes personalizado

El cargador de componentes personalizados se puede implementar de las siguientes maneras:

  • getConfig(name, callback)- Dependiendo de los nombres, podemos pasar configuraciones programáticamente. Podemos llamar a callback (componentConfig) para pasar las configuraciones, donde el objeto componentConfig puede ser usado por loadComponent o cualquier otro cargador.

  • loadComponent(name, componentConfig, callback)- Esta función resuelve el viewModel y la parte de la plantilla de config dependiendo de la forma en que esté configurado. Podemos llamar a callback (resultado) para pasar el par viewmodel / template, donde el resultado del objeto está definido por las siguientes propiedades.

    • template- Requerido. Devuelve una matriz de nodos DOM.

    • createViewModel(params, componentInfo)- Opcional. Devuelve el objeto viewModel según cómo se configuró la propiedad viewModel.

  • loadTemplate(name, templateConfig, callback)- Los nodos DOM se pasan en una plantilla usando lógica personalizada. El objeto templateConfig es una propiedad de la plantilla de un objeto componentConfig. Se llama a callback (domNodeArray) para pasar una matriz de nodos DOM.

  • loadViewModel(name, templateConfig, callback) - La fábrica viewModel se pasa en una configuración viewModel usando lógica personalizada.