2

私はノックアウトjsとアイソトープメイソンレイアウトを使用しており、カスタムバインディングはコードブログリンクに基づいており、以下に示されています:

意見:

<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を使用する必要があります。ここで詳細を読むhttp://knockoutjs.com/documentation/foreach-binding.htmlforeachafterAdd

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 に答える