我正在使用knockoutjs和同位素masonary布局,基于代码 blog link here 的自定义绑定,如下所示:
查看:
<div id="container" class="isotope" data-bind="foreach: bills">
<div class="item" data-bind="isotope: {container: '#container', itemSelector: '.item'}, style: {height: RandomHeight() + 'px'}">
<h3 data-bind="text: title"></h3>
<p>Votes: <span data-bind="text: votes"></span><p>
<p data-bind="text: desc"></p>
</div>
</div>
ViewModel和自定义绑定:
ko.bindingHandlers.isotope = function() {
var self = this;
self.init = function(element, valueAccessor, allBindings, viewModel, bindingContext) {
console.log("init...");
var value = ko.utils.unwrapObservable(valueAccessor());
var $container = $(value.container);
$container.isotope({
itemSelector: value.itemSelector,
masonry: {
columnWidth: 100
}
});
};
self.update = function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var $el = $(element);
var value = ko.utils.unwrapObservable(valueAccessor());
console.log("updating..." + value);
var $container = $(value.container);
$container.isotope('appended', $el);
};
return {
init: self.init,
update: self.update
}
}();
问题是当我添加一个新项目并将其附加到列表时,第一个项目从左向右跳转。顶部的项目应该保持静态定位,只有底部的项目应该随机播放,这个发生的示例屏幕截图(mid-jump_位于帖子的底部。
任何想法,我做错了吗?
小提琴在这里:http://jsfiddle.net/g18c/zoohcveh/4/
答案 0 :(得分:3)
您的同位素结合位于item
,如果您仔细阅读日志,同位素会在每次添加新项目时执行另一个初始化。这肯定会带来麻烦。
正确的方法是在顶级容器上使用同位素绑定,只启动一次。
但我们还需要保持(也称为扩展)foreach
绑定的行为。
要在添加新项目后触发isotope
的动画,您需要使用foreach
&#39; afterAdd
回调。在这里阅读更多http://knockoutjs.com/documentation/foreach-binding.html
http://jsfiddle.net/zoohcveh/27/
<强> HTML 强>
<div id="container" class="isotope" data-bind="isotope: bills, isotopeOptions: {
itemSelector: '.item',
masonry: {
columnWidth: 182
}
}">
<div class="item" data-bind="style: {height: RandomHeight() + 'px'}">
<h3 data-bind="text: title"></h3>
<p>Votes: <span data-bind="text: votes"></span></p>
<p data-bind="text: desc"></p>
</div>
</div>
<强> JS 强>
// use a factory method since most code of 'init' and 'update' are shared.
function initOrUpdate(method) {
return function(element, valueAccessor, allBindings, viewModel, bindingContext) {
function isotopeAppend(ele) {
// runs isotope animation
console.log('nodeType ' + ele.nodeType);
// nodeType 3 is Text (the empty space before and after div.item)
// nodeType 1 is element
if (ele.nodeType === 1) { // Element type
console.log("appended isotope");
$(element).isotope('appended', ele).isotope('layout');
}
}
function attachCallback(valueAccessor) {
return function() {
return {
data: valueAccessor(),
afterAdd: isotopeAppend,
};
};
}
// extend foreach binding
ko.bindingHandlers.foreach[method](element,
attachCallback(valueAccessor), // attach 'afterAdd' callback
allBindings, viewModel, bindingContext);
if (method === 'init') {
console.log('init...');
var options = allBindings.get('isotopeOptions') || {};
console.log("options " + JSON.stringify(options));
$(element).isotope(options);
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
$(element).isotope("destroy");
});
} else {
console.log("updating...");
}
}
}
ko.bindingHandlers.isotope = {
init: initOrUpdate('init'),
update: initOrUpdate('update')
};
<强>更新强>
要成为好公民,请为$(element).isotope("destroy");
添加处理回调。
答案 1 :(得分:1)
http://jsfiddle.net/zombiesplat/zoohcveh/17/这是我在下面回答的工作版本。
问题似乎是同位素v2和基因敲除的某种兼容性问题。我的修复来自查找此示例http://zubinraj.com/demo/isotope-knockout/isotope-knockout-binding.htm并将您的代码转换为使用knockout v1.5
HTML
<div>
<button data-bind="click: addNew">Add New</button>
</div>
<div id="container" class="isotope" data-bind="foreach: bills">
<div class="item" data-bind="isotope: {container: '#container', itemSelector: '.item'}, style: {height: RandomHeight() + 'px'}">
<h3 data-bind="text: title"></h3>
<p>Votes: <span data-bind="text: votes"></span><p>
<p data-bind="text: desc"></p>
</div>
</div>
CSS
/* ---- .item ---- */
.item {
float: left;
width: 380px;
background: #0D8;
border: 2px solid #333;
border-color: hsla(0, 0%, 0%, 0.7);
}
/* Begin Required Isotope Styles - see http://isotope.metafizzy.co for more info */
.isotope-item {
z-index: 2;
}
.isotope-hidden.isotope-item {
pointer-events: none;
z-index: 1;
}
/**** Isotope CSS3 transitions ****/
.isotope, .isotope .isotope-item {
-webkit-transition-duration: 0.8s;
-moz-transition-duration: 0.8s;
-ms-transition-duration: 0.8s;
-o-transition-duration: 0.8s;
transition-duration: 0.8s;
}
.isotope {
-webkit-transition-property: height, width;
-moz-transition-property: height, width;
-ms-transition-property: height, width;
-o-transition-property: height, width;
transition-property: height, width;
}
.isotope .isotope-item {
-webkit-transition-property: -webkit-transform, opacity;
-moz-transition-property: -moz-transform, opacity;
-ms-transition-property: -ms-transform, opacity;
-o-transition-property: -o-transform, opacity;
transition-property: transform, opacity;
}
/**** disabling Isotope CSS3 transitions ****/
.isotope.no-transition, .isotope.no-transition .isotope-item, .isotope .isotope-item.no-transition {
-webkit-transition-duration: 0s;
-moz-transition-duration: 0s;
-ms-transition-duration: 0s;
-o-transition-duration: 0s;
transition-duration: 0s;
}
Dom Ready上的Javascript
var $container = $("#container");
var data = [
{
title: "Test 1",
desc: "Some description text goes here",
votes: 1000,
category: "catA",
},
{
title: "Test 2",
desc: "Some description text goes here",
votes: 2000,
category: "catB",
},
{
title: "Test 3",
desc: "Some description text goes here",
votes: 100,
category: "catC",
}
];
function Bill(title, desc, votes, category)
{
var self = this;
self.title = ko.observable(title);
self.desc = ko.observable(desc);
self.votes = ko.observable(votes);
self.category = ko.observable(category);
self.RandomHeight = ko.observable(Math.floor(Math.random() * 200) + 400);
console.log("Added new bill");
};
function ViewModel() {
var self = this;
self.bills = ko.observableArray();
self.count = 1;
self.search = function() {
self.bills.removeAll();
for(var i=0; i<data.length; i++)
{
var bill = new Bill(
data[i].title,
data[i].desc,
data[i].votes,
data[i].category
);
self.bills.push(bill);
}
};
self.addNew = function() {
for(var i=0; i<data.length; i++)
{
var bill = new Bill(
self.count,
data[i].desc,
data[i].votes,
data[i].category
);
self.bills.push(bill);
self.count++;
}
};
};
ko.bindingHandlers.isotope = {
init : function(element, valueAccessor, allBindings, viewModel, bindingContext) {
},
update : function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var $el = $(element);
var value = ko.utils.unwrapObservable(valueAccessor());
console.log("updating..." + value);
var $container = $(value.container);
$container.isotope({
itemSelector: value.itemSelector,
masonry: {
columnWidth: 100
}
});
$container.isotope('appended', $el);
}
};
ko.applyBindings(new ViewModel());