utils tutorial que knockout example javascript mvvm knockout.js knockout-mapping-plugin

javascript - tutorial - observable knockout js



¿Estoy usando en exceso el plugin de mapeo Knockout utilizándolo siempre para hacer mi modelo de vista? (4)

Allen, mi reciente experiencia de aprendizaje con Knockout.js ha sido similar a la tuya. Trabajamos con un gráfico de objeto jerárquico profundo del servidor y he definido funciones de modelo de vista explícitamente instanciables que conservan la estructura básica del mismo.

Comencé definiendo cada propiedad explícitamente como observable en el modelo de vista relevante, pero eso rápidamente se salió de control. Además, una de las principales razones para cambiar al uso del plugin de mapeo fue que tenemos que hacer frecuentes publicaciones de Ajax del gráfico al servidor donde se fusionó con la versión persistente, y luego validadas en el servidor de tal manera que numerosas propiedades pueden se modifican los cambios y las colecciones, y se devuelve una nueva instancia como resultado de Ajax, donde se debe volver a fusionar con la representación del cliente. Eso se convirtió en algo realmente difícil, y el plugin de mapeo ayudó en gran medida al permitir la especificación de identificadores para resolver adiciones / eliminaciones / actualizaciones y reasignar un gráfico actualizado en el original.

También ayudó en la creación del gráfico original mediante el uso de la opción "crear" para los modelos de subvista. En cada constructor de modelo de vista, recibo una referencia al modelo de vista padre más los datos con los que construir el modelo de vista hijo, luego creo otras opciones de mapeo para crear nietos a partir de los datos secundarios pasados.

La única desventaja (leve) que encontré recientemente, como se detalla en esta pregunta , es que al hacer ko.mapping.toJSON no se engancha en ninguna anulación de JSON que pueda haber definido en los prototipos de sus modelos de vista para excluir propiedades de la serialización. Pude sortear eso al especificar ignorar opciones en el desemparejamiento, tal como lo recomendó Ryan Niemeyer en esa publicación.

Entonces, en resumen, definitivamente me quedaré con el plugin de mapeo. Las reglas de Knockout.js

Todavía estoy aprendiendo el uso correcto de Knockout y me he encontrado rápidamente ko.observable escribir ko.observable al configurar mi viewmodel y en su lugar simplemente definiendo un objeto literal y pasándolo a través del plugin de mapeo con algo como

var viewModel = ko.mapping.fromJS(data);

o al menos, algo parecido a rellenar todos mis datos en un atributo en viewModel como tal

var viewModel = { ... events etc ... , "data": ko.mapping.fromJS(data) }

Para ser sincero, la razón principal por la que he estado haciendo esto es para tener que escribir ko.observable y ko.observableArray repetitivamente. Solo estoy tratando de averiguar si este es un buen enfoque y si hay algunas desventajas al var x = ko.observable() declaración específica var x = ko.observable() . Además, estoy haciendo todo esto con carga, no en respuesta a ninguna llamada ajax, etc., que por lo que puedo decir, es para lo que se diseñó el plugin de mapeo.

En su trabajo con el knockout, ¿todavía declara los observables de forma manual, uno por uno, o se ha ido con el mapping.from método JS que yo uso? ¿Hay algún inconveniente específico al uso del plugin de mapeo tan frecuentemente como este?

Editar:

Ejemplo específico

En este artículo , Steve configura su viewModel haciendo

var initialData = [ { ... } , { ... } ]; // json from the serializer var viewModel = { gifts : ko.observableArray(initialData) };

Normalmente, también usaría ko.mapping.fromJS para esta situación, específicamente para asegurarme de que los objetos dentro de la matriz también se vuelvan observables. Mirando lo que hizo, mi enfoque parece ser excesivo y agrega un poco de sobrecarga innecesaria.


Después de usar Knockout por un poco más de tiempo, he notado que el plugin de mapeo tiene algunas opciones adicionales que le dan un control mucho más detallado sobre el proceso de mapeo.

Tipo de control y cantidad de propiedades generadas

Hay varias formas de lograr esto, y revisaré algunas, pero el resultado final es que terminas obteniendo un resultado más ligero del plugin de mapeo porque no todo es observable.

Básicamente, deja todo lo que no cree que va a cambiar, como una propiedad normal y solo hace observables los elementos específicos que desea observar.

Hacer que el mapping omita ciertas propiedades

Puede hacer que el complemento de mapeo omita las propiedades por completo del resultado final al especificar cosas como ignore o include . Ambos logran lo mismo, solo de maneras opuestas.

Nota: Las muestras provienen de la documentación del plugin de asignación de knockout.js , comentarios agregados por mí

Argumento del plugin de mapeo: include

El siguiente fragmento omitirá todas las propiedades del objeto fuente distintas de las pasadas a través del argumento include .

// specify the specific properties to include as observables in the end result var mapping = { // only include these two properties ''include'': ["propertyToInclude", "alsoIncludeThis"] } // viewModel will now only contain the two properties listed above, // and they will be observable var viewModel = ko.mapping.fromJS(data, mapping);

Argumento del plugin de mapeo: ignore

Si solo desea omitir ciertas propiedades del objeto de origen, use el argumento de ignore como se muestra a continuación. Hará observables de todas las propiedades en el objeto fuente a excepción de las propiedades especificadas.

// specify the specific properties to omit from the result, // all others will be made observable var mapping = { // only ignore these two properties ''ignore'': ["propertyToIgnore", "alsoIgnoreThis"] } // viewModel will now omit the two properties listed above, // everything else will be included and they will be an observable var viewModel = ko.mapping.fromJS(data, mapping);

Controle qué propiedades son o no hechas observables

Si necesita incluir propiedades pero no cree que deban hacerse observables (por alguna razón), el complemento de mapeo tiene algo que puede ayudar.

Argumento del plugin de mapeo: copy

Si desea que el complemento de mapeo simplemente copie las propiedades simples y no las haga observables, utilice este argumento, como se muestra a continuación.

// tell the mapping plugin to handle all other properties normally, // but to simply copy this property instead of making it observable var mapping = { ''copy'': ["propertyToCopy"] } var viewModel = ko.mapping.fromJS(data, mapping);

Obtenga control completo sobre el proceso de mapeo

Si desea tener el 100% de control sobre lo que se crea en el proceso de asignación, incluida la capacidad de poner cierres y suscripciones en sus objetos , entonces desea utilizar la opción "crear".

resultado simple con propiedades calculadas

Aquí hay un ejemplo en el que estaba mapeando datos desde una llamada ajax a un objeto con una propiedad de results . No quería que nada fuera observable y solo quería una propiedad generada simple que estaría hecha de otras propiedades simples en el objeto. Tal vez no sea el ejemplo más convincente pero demuestra la funcionalidad.

var searchMappingConfig = { // specific configuration for mapping the results property "results": { // specific function to use to create the items in the results array "create": function (options) { // return a new function so we can have the proper scope/value for "this", below return new function () { // instead of mapping like we normally would: ko.mapping.fromJS(options.data, {}, this); // map via extend, this will just copy the properties from the returned json element to "this" // we''ll do this for a more light weight vm since every last property will just be a plain old property instead of observable $.extend(this, options.data); // all this to add a vehicle title to each item this.vehicleTitle = this.Year + "<br />" + this.Make + " " + this.Model; }, this); }; } } }

suscripciones y cierres y mapeo, oh mi

Otra situación es si desea cierres y suscripciones en su resultado. Este ejemplo es demasiado largo para ser incluido en su totalidad, pero es para una jerarquía de marca / modelo de vehículo. Quería que todos los modelos (niños) para un make (padre) determinado se deshabilitaran si el modelo no estaba habilitado y quería que esto se hiciera con una suscripción.

// here we are specifying the way that items in the make array are created, // since makes has a child array (Models), we will specify the way that // items are created for that as well var makesModelsMappingConfig = { // function that has the configuration for creating makes "create": function (options) { // return a new function so we can have the proper // scope/value for "this", below return new function () { // Note: we have a parent / child relationship here, makes have models. In the // UI we are selecting makes and then using that to allow the user to select // models. Because of this, there is going to be some special logic in here // so that all the child models under a given make, will automatically // unselect if the user unselects the parent make. // make the selected property a private variable so it can be closure''d over var makeIsSelected = ko.protectedComputed(false); // expose our property so we can bind in the UI this.isSelected = makeIsSelected; // ... misc other properties and events ... // now that we''ve described/configured how to create the makes, // describe/configure how to create the models under the makes ko.mapping.fromJS(options.data, { // specific configuration for the "Models" property "Models": { // function that has the configuration for creating items // under the Models property "create": function (model) { // we''ll create the isSelected as a local variable so // that we can flip it in the subscription below, // otherwise we wouldnt have access to flip it var isSelected = ko.protectedComputed(false); // subscribe to the parents "IsSelected" property so // the models can select/unselect themselves parentIsSelected.current.subscribe(function (value) { // set the protected computed to the same // value as its parent, note that this // is just protected, not the actual value isSelected(value); }); // this object literal is what makes up each item // in the Models observable array return { // here we''re returning our local variable so // we can easily modify it in our subscription "isSelected": isSelected, // ... misc properties to expose // under the item in the Model array ... }; } } }, this); }; } };

En general, lo que he descubierto es que rara vez necesita el 100% de un objeto que pasaría al plugin y rara vez necesita que el 100% sea observable. Excavar con las opciones de configuración de mapeo y crear todo tipo de objetos complejos y simples. La idea es obtener solo todo lo que necesita, nada más o menos.


Mi sugerencia para usted sería la misma otra preguntada que acabo de responder en https://.com/questions/7499133/mapping-deeply-hierarchical-objects-to-custom-classes-using-knockout-mapping-plug.

Su razonamiento para utilizar el complemento de mapeo es razonable y el que yo uso. ¿Por qué escribir más código de lo necesario?

En mi experiencia con el knockout (todos los 4 meses), he descubierto que cuanto menos hago manualmente y dejo que las rutinas eliminatorias hagan lo suyo, mejores parecen que se ejecuten mis aplicaciones. Mi sugerencia es intentar el enfoque más simple primero. Si no satisface sus necesidades, observe cómo lo hace el enfoque simple es "cosa" y determine qué debe cambiar para satisfacer sus necesidades.


Un add-on más simple pero completo podría ser knockout-data-projections

Actualmente, no maneja js para ver las asignaciones de modelos, pero maneja bastante bien el modelo para las asignaciones de JS.