javascript jquery knockout.js masonry

javascript - aplicar automáticamente albañilería en el manipulador de encuadernación a prueba de golpes después de la actualización dinámica



jquery knockout.js (1)

Depende de lo que quiera decir después de que el contenedor masonsy se haya actualizado. ¿Quiere decir cambiar el tamaño o tal vez cargar nuevos elementos? Si sabe cuándo debe actualizar el contenedor, puede hacerlo así:

ko.bindingHandlers.masonry = { init: function(element, valueAccessor, allBindingsAccessor) { ko.computed(function () { var options = ko.unwrap(valueAccessor()); ko.unwrap(allBindingsAccessor().masonryUpdater); $(element).masonry(''destroy''); $(element).masonry(options); }, null, disposeWhenNodeIsRemoved: element); } } // ... vm.masonryUpdater = ko.observable(); // When you need to update just run vm.masonryUpdater.valueHasMutated();

Y aplique su encuadernación así:

<div class="grid" data-bind="masonry: {itemSelector: ''.item'', columnWidth: 200}, masonryUpdater: masonryUpdater, foreach: items"> <div class="item"> <p data-bind="text:name"></p> <p data-bind="text:language"></p> </div> </div>

Entonces, Que esta pasando aquí:

  1. Creamos una suscripción a un allBindingsAccessor().masonryUpdater leyéndolo. De esta forma cada vez que actualice el computado que creamos se reevaluará y volverá a aplicar la mampostería.
  2. Para decirle a knockout que nuestro observable ha cambiado, llamamos a vm.masonryUpdater.valueHasMutated();
  3. El cálculo se realizará de forma segura después de que se elimine nuestro elemento de cuadrícula

Este tipo de aspecto es vudú, y algunos pueden decir que estamos explotando los efectos secundarios. Bueno, tal vez solo un poco. En el lado positivo, estamos haciendo las cosas bastante simples para nosotros. Todo lo que se necesita hacer una vez se ejecuta fuera de cálculo, todo lo que necesita ser una dependencia o actualización dentro de computados. También es más fácil depurar y guardar datos para un uso posterior.

Se describe con cierto detalle aquí http://www.knockmeout.net/2012/06/knockoutjs-performance-gotcha-3-all-bindings.html

Estoy utilizando knockoutjs con mampostería y he creado un manipulador de encuadernación a prueba de golpes personalizado para aplicar mampostería a un elemento html.

El contenedor al que quiero aplicar mampostería tiene su contenido inyectado dinámicamente utilizando el enlace foreach de knockout.

El problema que estoy teniendo es conseguir que la mampostería se aplique después de que el contenedor de mampostería se haya actualizado dinámicamente.

En el ejemplo del fragmento de código, si hace clic en el botón de mampostería, destruirá el contenedor de mampostería y volverá a aplicar la mansión, ¿cómo puedo obtener este comportamiento en mi controlador de enlace?

ko.bindingHandlers.masonry = { update: function(element, valueAccessor) { var options = valueAccessor(); $(element).masonry(options); } } var vm = { term: ko.observable(), page: ko.observable(1), per_page: ko.observable(3), items: ko.observableArray(), masonryize: function() { $(''.grid'').masonry(''destroy''); $(''.grid'').masonry({ itemSelector: ''.item'', columnWidth: 200 }); }, getStuff: function() { $.ajax({ url: ''https://api.github.com/search/repositories'', method: ''GET'', data: { q: this.term, page: this.page(), per_page: this.per_page() } }).then(function(r) { this.items(r.items) }.bind(this)) } } ko.applyBindings(vm);

.grid { width: 400px; } .item { margin-bottom: 2em; border: 1px solid black; }

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="http://masonry.desandro.com/masonry.pkgd.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> <div> <label>term:</label> <input type="text" data-bind="value: term" /> </div> <div> <label>page:</label> <input type="text" data-bind="value: page" /> </div> <div> <label>no of items:</label> <input type="text" data-bind="value: per_page" /> </div> <div> <button data-bind="click: getStuff">get stuff</button> <button data-bind="click: masonryize">masonryize</button> </div> <div class="grid" data-bind="masonry: {itemSelector: ''.item'', columnWidth: 200}, foreach: items"> <div class="item"> <p data-bind="text:name"></p> <p data-bind="text:language"></p> </div> </div>