2

我正在使用 knockoutjs 和同位素砌体布局,自定义绑定基于此处的代码博客链接,如下所示:

看法:

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

跳砖

4

2 回答 2

3

你的同位素绑定是在一个item,如果你仔细阅读日志,每次你添加新项目时,同位素都会进行另一个初始化。这肯定会带来麻烦。

正确的方法是在顶层容器上使用同位素绑定,只初始化一次。但是我们还需要保持(也就是扩展)foreach绑定的行为。

要在添加新项目后触发动画isotope,您需要使用foreach'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");.

于 2014-08-15T03:10:55.830 回答
1

http://jsfiddle.net/zombiesplat/zoohcveh/17/这是我在下面回答的工作版本。

问题似乎是与同位素 v2 和淘汰赛的某种兼容性问题。我的修复来自找到这个示例http://zubinraj.com/demo/isotope-knockout/isotope-knockout-binding.htm并将您的代码转换为使用淘汰赛 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());
于 2014-08-12T18:19:15.080 回答