javascript knockout.js progressive-enhancement

javascript - Mejora progresiva con KnockoutJS



knockout.js progressive-enhancement (6)

Me temo que no hay una forma clara de hacerlo. Personalmente renderizo la página en el back-end y luego paso los mismos datos contextuales a la interfaz (serializados como JSON) y configuré Knockout usándolo. Esto significa que hay algo de duplicación. Quizás cambiar el backend a node.js simplificaría las cosas aquí.

Digamos que tenemos datos de la siguiente manera

var data = { facets: [{ name : "some name", values: [{ value: "some value" }] }] };

Podemos representarlo fácilmente como un modelo de vista ligado a una plantilla knockout de la siguiente manera:

<ul data-bind="foreach: facets"> <li> <span data-bind="text: name"></span> <ul data-bind="foreach: values"> <li data-bind="text: value"></li> </ul> </li> </ul>

La pregunta es, ¿cómo podemos lograr el mismo resultado cuando usamos la mejora progresiva? Esto es haciendo que la plantilla se represente inicialmente en el servidor y luego vincule la plantilla knockout y el modelo de vista a esa representación.

Una plantilla simple del lado del servidor se vería así:

<ul> <li> <span>some name</span> <ul> <li>some value</li> </ul> </li> </ul>

He explorado algunas posibilidades diferentes:

  • Una es crear una plantilla knockout y una plantilla del lado del servidor, y generar el modelo de vista Knockout dinámicamente mediante el análisis del DOM para la plantilla del lado del servidor. De esta forma, solo la plantilla Knockout sería visible cuando JavaScript esté habilitado, y solo la plantilla del lado del servidor estaría visible si JavaScript está deshabilitado. Podrían ser diseñados de una manera para que se vean idénticos.

  • Otro enfoque es aplicar enlaces para cada elemento en el conjunto de facetas por separado al elemento DOM existente para esa faceta. Sin embargo, este solo tiene un nivel de profundidad y no funciona para los elementos anidados.

Ninguno de estos enfoques parece bastante limpio. Otra solución podría ser escribir un enlace personalizado que maneje todo el renderizado y reutilice elementos existentes si es posible.

¿Alguna otra idea?


Simplemente agregue los diversos atributos de data- en las plantillas del lado del servidor. No perjudican si JavaScript está desactivado, por lo que tenerlos no es un problema en absoluto.


Exploré varios enfoques aquí, incluida la generación de una plantilla anónima a partir del primer elemento, como se describe aquí:

http://groups.google.com/group/knockoutjs/browse_thread/thread/3896a640583763d7

o crear enlaces separados para cada elemento de la matriz a través de un enlace personalizado, como

ko.bindingHandlers.prerenderedArray = { init: function(element, valueAccessor, allBindingsAccessor, viewModel) { var binding = valueAccessor(); binding.firstTime = true; $(element).children().each(function(index, node) { var value = ko.utils.unwrapObservable(binding.value)[index]; ko.applyBindings(value, node); }); return { ''controlsDescendantBindings'': true }; }, update: function (element, valueAccessor, allBindingsAccessor, viewModel) { var binding = valueAccessor(); if (binding.firstTime) { binding.firstTime = false; return; } $(element).children().remove(); ko.applyBindingsToNode(element, { template: { name: binding.template, foreach: binding.value }}, viewModel) } };

que aplica un enlace específico a cada elemento y luego en la primera actualización reemplaza el contenido con un enlace foreach ordinario. Este enfoque todavía significa que aún necesita tener dos plantillas. Ambos también implican inicializar el estado a través de un JSON procesado por el servidor.

El enfoque actual que elegí usar (aunque todavía está sujeto a cambios) es poner todas las plantillas Knockout dentro de las etiquetas de script para que nunca se procesen en navegadores NoJS. Las plantillas NoJS se representan como contenido de un div en el lado del servidor. Tan pronto como se procesa la plantilla Knockout, el contenido del div se reemplazará por la plantilla Knockout en las etiquetas del script. Puede diseñarlos de forma idéntica / similar para que la transición sea perfecta, y si esto no es posible, oculte la plantilla noJS a través de CSS.

Al final, llegué a la conclusión de que Knockout.js y la mejora progresiva en realidad no funcionan muy bien juntos, uno debe elegir el otro, es decir, construir algunas partes de la aplicación que requieren una mejora progresiva utilizando métodos más tradicionales como jQuery directo. Manipulación DOM


aquí , sugerí un enlace de plantilla que usa el HTML generado del servidor. Su uso es similar al enlace de plantilla original, excepto por los pocos atributos de datos que usará el enlace.



Aquí está mi opinión, este ejemplo básico usa un enlace personalizado para cargar los valores del lado del servidor en el modelo de vista.

Mejora progresiva con KnockoutJS Infinite Scroll

Encuadernación de mejora progresiva

ko.bindingHandlers.PE = { init: function(element, valueAccessor, allBindings) { var bindings = allBindings(); if (typeof bindings.text === ''function'') { bindings.text($(element).text()); } } };