Estoy construyendo funcionalidad en una página web que el usuario puede realizar varias veces. A través de la acción del usuario, se crea un objeto / modelo y se aplica a HTML usando ko.applyBindings ().
El HTML enlazado a datos se crea a través de plantillas jQuery.
Hasta aquí todo bien.
Cuando repito este paso creando un segundo objeto / modelo y llamo a ko.applyBindings () encuentro dos problemas:
- El marcado muestra el objeto / modelo anterior, así como el nuevo objeto / modelo.
- Se produce un error de javascript relacionado con una de las propiedades del objeto / modelo, aunque todavía se muestra en el marcado.
Para solucionar este problema, después de la primera pasada, llamo a .empty () de jQuery para eliminar la plantilla HTML que contiene todos los atributos de enlace de datos, de modo que ya no esté en el DOM. Cuando el usuario inicia el proceso para la segunda pasada, el HTML enlazado a datos se vuelve a agregar al DOM.
Pero como dije, cuando el HTML se vuelve a agregar al DOM y se vuelve a vincular al nuevo objeto / modelo, todavía incluye datos del primer objeto / modelo, y todavía obtengo el error JS que no ocurre durante la primera pasada.
La conclusión parece ser que Knockout se aferra a estas propiedades vinculadas, aunque el marcado se elimine del DOM.
Entonces, lo que estoy buscando es un medio para eliminar estas propiedades enlazadas de Knockout; decirle al nocaut que ya no hay un modelo observable. ¿Hay alguna forma de hacer esto?
EDITAR
El proceso básico es que el usuario carga un archivo; el servidor luego responde con un objeto JSON, el HTML enlazado a datos se agrega al DOM, luego el modelo de objeto JSON se enlaza a este HTML usando
mn.AccountCreationModel = new AccountViewModel(jsonData.Account);
ko.applyBindings(mn.AccountCreationModel);
Una vez que el usuario ha realizado algunas selecciones en el modelo, el mismo objeto se vuelve a enviar al servidor, el HTML enlazado a datos se elimina del DOM, y luego tengo el siguiente JS
mn.AccountCreationModel = null;
Cuando el usuario desea hacer esto una vez más, se repiten todos estos pasos.
Me temo que el código está demasiado "complicado" para hacer una demostración de jsFiddle.
init
función en la que se le pasan los datos a aplicar?Respuestas:
¿Ha intentado llamar al método de nodo limpio de knockout en su elemento DOM para deshacerse de los objetos enlazados en memoria?
Luego, la aplicación de los enlaces de eliminación de nuevo solo en ese elemento con sus nuevos modelos de vista actualizaría su enlace de vista.
fuente
delete
a ciertas teclas en los elementos dom, que aparentemente es donde se almacena toda la magia del knockout. Si alguien tiene una fuente sobre documentación, se lo agradecería mucho.Para un proyecto en el que estoy trabajando, escribí una
ko.unapplyBindings
función simple que acepta un nodo jQuery y el booleano remove. Primero desvincula todos los eventos de jQuery ya que elko.cleanNode
método no se ocupa de eso. He probado las pérdidas de memoria y parece funcionar bien.fuente
ko.cleanNode()
llamar y no se reemplazó el HTML completo.Puede intentar usar el enlace con que ofrece knockout: http://knockoutjs.com/documentation/with-binding.html La idea es usar aplicar enlaces una vez, y siempre que sus datos cambien, simplemente actualice su modelo.
Supongamos que tiene un modelo de vista de nivel superior storeViewModel, su carrito representado por cartViewModel y una lista de artículos en ese carrito, digamos cartItemsViewModel.
Vincularía el modelo de nivel superior, el storeViewModel a toda la página. Luego, puede separar las partes de su página que son responsables de los artículos del carrito o del carrito.
Supongamos que cartItemsViewModel tiene la siguiente estructura:
CartItemsViewModel puede estar vacío al principio.
Los pasos se verían así:
Defina enlaces en html. Separe el enlace cartItemsViewModel.
El modelo de tienda proviene de su servidor (o se crea de cualquier otra manera).
var storeViewModel = ko.mapping.fromJS(modelFromServer)
Defina modelos vacíos en su modelo de vista de nivel superior. Luego, una estructura de ese modelo se puede actualizar con datos reales.
Vincular el modelo de vista de nivel superior.
ko.applyBindings(storeViewModel);
Cuando el objeto cartItemsViewModel esté disponible, asígnelo al marcador de posición definido previamente.
storeViewModel.cartItemsViewModel(actualCartItemsModel);
Si desea limpiar los artículos del carrito:
storeViewModel.cartItemsViewModel(null);
Knockout se encargará de html, es decir, aparecerá cuando el modelo no esté vacío y el contenido de div (el que tiene "con enlace") desaparecerá.
fuente
Tengo que llamar a ko.applyBinding cada vez que hago clic en el botón de búsqueda, y los datos filtrados se devuelven desde el servidor, y en este caso, el siguiente trabajo para mí sin usar ko.cleanNode.
Experimenté, si reemplazamos foreach con template, entonces debería funcionar bien en el caso de colecciones / observableArray.
Puede encontrar útil este escenario.
fuente
En lugar de usar las funciones internas de KO y lidiar con la eliminación del controlador de eventos general de JQuery, una idea mucho mejor es usar enlaces
with
otemplate
. Cuando haces esto, ko vuelve a crear esa parte de DOM y así se limpia automáticamente. Esta también es la forma recomendada, consulte aquí: https://stackoverflow.com/a/15069509/207661 .fuente
Creo que sería mejor mantener el enlace todo el tiempo y simplemente actualizar los datos asociados con él. Me encontré con este problema y descubrí que simplemente llamar usando el
.resetAll()
método en la matriz en la que estaba guardando mis datos era la forma más efectiva de hacerlo.Básicamente, puede comenzar con una var global que contiene datos que se procesarán a través de ViewModel:
Me tomó un tiempo darme cuenta de que no podía simplemente hacer
myLiveData
una matriz normal, lako.oberservableArray
parte era importante.Entonces puedes seguir adelante y hacer lo que quieras
myLiveData
. Por ejemplo, haz una$.getJSON
llamada:Una vez que haya hecho esto, puede continuar y aplicar enlaces usando su ViewModel como de costumbre:
Luego, en el HTML, use
myData
como lo haría normalmente.De esta manera, puede simplemente jugar con myLiveData desde cualquier función. Por ejemplo, si desea actualizar cada pocos segundos, simplemente envuelva esa
$.getJSON
línea en una función y llámelasetInterval
. Nunca necesitará quitar la encuadernación siempre que recuerde mantener lamyLiveData.removeAll();
línea dentro.A menos que sus datos sean realmente enormes, el usuario ni siquiera podrá notar el tiempo entre el reinicio de la matriz y luego volver a agregar los datos más recientes.
fuente
Recientemente tuve un problema de pérdida de memoria y
ko.cleanNode(element);
no lo haría por mí, loko.removeNode(element);
hice. Fuga de memoria de Javascript + Knockout.js: ¿cómo asegurarse de que el objeto se esté destruyendo?fuente
Has pensado sobre esto:
Se me ocurrió esto porque en Knockout encontré este código
Entonces, para mí, no es realmente un problema que ya esté vinculado, es que el error no fue detectado y tratado ...
fuente
Descubrí que si el modelo de vista contiene muchos enlaces div, la mejor manera de borrar el
ko.applyBindings(new someModelView);
es usar:ko.cleanNode($("body")[0]);
Esto le permite llamar a un nuevoko.applyBindings(new someModelView2);
modelo dinámicamente sin la preocupación de que el modelo de vista anterior aún esté enlazado.fuente
$("body")[0]
esdocument.body
.