动态更新后,在knockout绑定处理程序中自动应用masonry

时间:2015-07-23 17:25:06

标签: javascript jquery knockout.js masonry

我正在使用knockoutjsmasonry并创建了一个自定义的淘汰赛绑定处理程序,以将砌体应用于html元素。

我想要应用砌体的容器使用knockout foreach绑定动态注入内容。

我遇到的问题是在砌体容器动态更新后,自行应用砌体。

在代码段示例中,如果您单击 masonryize 按钮,它将销毁砌体容器并重新应用mansonry,如何将此行为引入我的绑定处理程序?< / p>

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>

1 个答案:

答案 0 :(得分:2)

在masonsy容器更新后,这取决于你的意思。你的意思是调整大小或加载新项目?如果你知道容器何时需要更新,你可以这样做:

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();

并像这样应用你的绑定:

<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>

所以这里发生了什么:

  1. 我们通过阅读来创建对可观察allBindingsAccessor().masonryUpdater的订阅。这样,无论何时更新计算,我们创建都将重新评估并重新应用砌体。
  2. 告诉我们我们的观察结果发生了变化,我们称之为vm.masonryUpdater.valueHasMutated();
  3. 删除网格元素后,将安全地处理计算
  4. 这种看起来像伏都教,加上有些人可能会说我们正在利用副作用。好吧也许只是一点点。从好的方面来说,我们为自己制作的东西非常简单。需要完成的所有事情都是在计算之外执行的,所有需要依赖的内容或计算内部的更新。调试和保存数据以供以后使用也更容易。

    这里将详细介绍http://www.knockmeout.net/2012/06/knockoutjs-performance-gotcha-3-all-bindings.html