动态更新后自动在敲除绑定处理程序中应用砌体
auto apply masonry in knockout binding handler after dynamic update
我正在使用 knockoutjs with masonry 并创建了自定义挖空绑定处理程序以将砌体应用到 html 元素。
我想应用砌体的容器使用 knockout 的 foreach
绑定动态注入了内容。
我遇到的问题是在动态更新砌体容器后让砌体自行应用。
在代码片段示例中,如果您单击 masonryize 按钮,它将 destroy masonry 容器并重新应用 mansonry,我如何获得这种行为进入我的绑定处理程序?
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>
这取决于你在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>
所以这里发生了什么:
- 我们通过读取它来创建对可观察对象
allBindingsAccessor().masonryUpdater
的订阅。这样,每当它更新我们创建的计算时,都会重新评估并重新应用砌体。
- 为了告诉 knockout 我们的 observable 已经改变,我们调用
vm.masonryUpdater.valueHasMutated();
- 我们的网格元素被移除后计算的将被安全地处理
这种看起来像巫术,而且有些人可能会说我们在利用副作用。好吧,也许只有一点点。从好的方面来说,我们正在让事情变得非常简单。所有需要做一次的事情都在计算外执行,所有需要依赖或更新的事情都在计算内执行。也更容易调试和保存数据以备后用。
这里描述的比较详细http://www.knockmeout.net/2012/06/knockoutjs-performance-gotcha-3-all-bindings.html
我正在使用 knockoutjs with masonry 并创建了自定义挖空绑定处理程序以将砌体应用到 html 元素。
我想应用砌体的容器使用 knockout 的 foreach
绑定动态注入了内容。
我遇到的问题是在动态更新砌体容器后让砌体自行应用。
在代码片段示例中,如果您单击 masonryize 按钮,它将 destroy masonry 容器并重新应用 mansonry,我如何获得这种行为进入我的绑定处理程序?
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>
这取决于你在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>
所以这里发生了什么:
- 我们通过读取它来创建对可观察对象
allBindingsAccessor().masonryUpdater
的订阅。这样,每当它更新我们创建的计算时,都会重新评估并重新应用砌体。 - 为了告诉 knockout 我们的 observable 已经改变,我们调用
vm.masonryUpdater.valueHasMutated();
- 我们的网格元素被移除后计算的将被安全地处理
这种看起来像巫术,而且有些人可能会说我们在利用副作用。好吧,也许只有一点点。从好的方面来说,我们正在让事情变得非常简单。所有需要做一次的事情都在计算外执行,所有需要依赖或更新的事情都在计算内执行。也更容易调试和保存数据以备后用。
这里描述的比较详细http://www.knockmeout.net/2012/06/knockoutjs-performance-gotcha-3-all-bindings.html