Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Knockout.js 对于砌体的自定义绑定,如何适当调整容器的大小_Knockout.js_Jquery Masonry_Bindinghandlers - Fatal编程技术网

Knockout.js 对于砌体的自定义绑定,如何适当调整容器的大小

Knockout.js 对于砌体的自定义绑定,如何适当调整容器的大小,knockout.js,jquery-masonry,bindinghandlers,Knockout.js,Jquery Masonry,Bindinghandlers,基于给出的建议和关于如何为forEach创建自定义bindingHandler的信息,我决定尝试为forEach和forEach编写自己的自定义绑定 由于元素是动态添加的,因此不会重新绘制和移动元素以填充空间。因此,在呈现元素或添加每个项目后调用元素后,需要移动此功能 这是我的bindingHandler ko.bindingHandlers.masonry = { init: function (element, valueAccessor, allBindingsAccessor) {

基于给出的建议和关于如何为forEach创建自定义bindingHandler的信息,我决定尝试为forEach和forEach编写自己的自定义绑定

由于元素是动态添加的,因此不会重新绘制和移动元素以填充空间。因此,在呈现元素或添加每个项目后调用元素后,需要移动此功能

这是我的bindingHandler

ko.bindingHandlers.masonry = {
init: function (element, valueAccessor, allBindingsAccessor) {
    var $element = $(element),
        originalContent = $element.html();
    $element.data("original-content", originalContent);
    //var msnry = new Masonry($element);
    return { controlsDescendantBindings: true }

},
update: function (element, valueAccessor, allBindingsAccessor) {
    var value = ko.utils.unwrapObservable(valueAccessor()),

    //get the list of items
    items = value.items(),

    //get a jQuery reference to the element
    $element = $(element),

    //get the current content of the element
    elementContent = $element.data("original-content");

    $element.html("");

    var container = $element[0];
    var msnry = new Masonry(container);

    for (var index = 0; index < items.length; index++) {
        (function () {
            //get the list of items
            var item = ko.utils.unwrapObservable(items[index]),
                $childElement = $(elementContent);

            ko.applyBindings(item, $childElement[0]);

            //add the child to the parent        
            $element.append($childElement);
            msnry.appended($childElement[0]);

        })();

        msnry.layout();
        msnry.bindResize();
    }
}

};
ko.bindingHandlers.mashine={
init:function(元素、valueAccessor、allBindingsAccessor){
变量$element=$(element),
originalContent=$element.html();
$element.data(“原始内容”,原始内容);
//var msnry=新砌体($构件);
返回{ControlsDescentBindings:true}
},
更新:函数(元素、valueAccessor、allBindingsAccessor){
var value=ko.utils.unwrapobbservable(valueAccessor()),
//获取项目列表
items=值。items(),
//获取对元素的jQuery引用
$element=$(element),
//获取元素的当前内容
elementContent=$element.data(“原始内容”);
$element.html(“”);
var容器=$element[0];
var msnry=新砌体(容器);
对于(var索引=0;索引
以及实现处理程序的HTML

<div id="criteriaContainer" data-bind="masonry: { items: SearchItems.Items }">
    <div class="searchCriterion control-group">
        <label class="control-label" data-bind="text: Description"></label>
        <div class="controls">
            <input type="hidden" data-bind="value: Value, select2: { minimumInputLength: 3, queryUri: SearchUri(), placeholder: Placeholder(), allowClear: true }" style="width: 450px">
        </div>
        <p data-bind="text: Value"></p>
    </div>
</div>

当它显示在页面上时,如果通过append方法呈现的元素彼此重叠,那么它将堆叠所有元素

您可以看到,在我的bindingHandler中,我调用了bindResize和layout(),这两个函数似乎都没有任何效果

下面是它在UI中的屏幕截图。

我制作的定制活页夹基于其他人的同位素定制活页夹:

注:自定义同位素绑定的作者正在使用修改版的敲除。下面的绑定使用标准的敲除库(我使用的是v3.3.0)

让自定义绑定工作的诀窍是使用afterAdd回调跟踪添加的元素,以便将它们附加到砌体对象

"use strict";

(function () {
    var $container, haveInitialized, newNodes = [], itemClass, masonryOptions;

    function afterAdd(node, index, item) {
        if (node.nodeType !== 1) {
            return; // This isn't an element node, nevermind
        }
        newNodes.push(node);
    }

    ko.bindingHandlers.masonry = {
        defaultItemClass: 'grid-item',
        // Wrap value accessor with options to the template binding,
        // which implements the foreach logic
        makeTemplateValueAccessor: function (valueAccessor) {
            return function () {
                var modelValue = valueAccessor(),
                    options,
                    unwrappedValue = ko.utils.peekObservable(modelValue);    // Unwrap without setting a dependency here

                options = {
                    afterAdd: afterAdd
                };

                // If unwrappedValue.data is the array, preserve all relevant
                // options and unwrap value so we get updates
                ko.utils.unwrapObservable(modelValue);
                ko.utils.extend(options, {
                    'foreach': unwrappedValue.data,
                    'as': unwrappedValue.as,
                    'includeDestroyed': unwrappedValue.includeDestroyed,
                    'templateEngine': ko.nativeTemplateEngine.instance
                });
                return options;
            };
        },
        'init': function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            console.log({ msg: 'Initializing binding' });

            itemClass = ko.bindingHandlers.masonry.defaultItemClass;
            masonryOptions = {};
            haveInitialized = false;
            $container = $(element);

            var parameters = ko.utils.unwrapObservable(valueAccessor());
            if (parameters && typeof parameters == 'object' && !('length' in parameters)) {
                if (parameters.masonryOptions) {
                    var clientOptions;
                    if (typeof parameters.masonryOptions === 'function') {
                        clientOptions = parameters.masonryOptions();
                        if (typeof clientOptions !== 'object') {
                            throw new Error('masonryOptions callback must return object');
                        }
                    } else if (typeof parameters.masonryOptions !== 'object') {
                        throw new Error('masonryOptions must be an object or function');
                    } else {
                        clientOptions = parameters.masonryOptions;
                    }
                    ko.utils.extend(masonryOptions, clientOptions);
                }
                if (parameters.itemClass) {
                    itemClass = parameters.itemClass;
                }
            }

            // Initialize template engine, moving child template element to an
            // "anonymous template" associated with the element
            ko.bindingHandlers.template.init(
                element,
                ko.bindingHandlers.masonry.makeTemplateValueAccessor(valueAccessor)
            );

            return { controlsDescendantBindings: true };
        },
        'update': function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            ko.bindingHandlers.template.update(element,
                    ko.bindingHandlers.masonry.makeTemplateValueAccessor(valueAccessor),
                    allBindingsAccessor, viewModel, bindingContext);

            // Make this function depend on the view model, so it gets called for updates
            var data = ko.bindingHandlers.masonry.makeTemplateValueAccessor(
                        valueAccessor)().foreach;
            ko.utils.unwrapObservable(data);

            if (!haveInitialized) {
                masonryOptions.itemSelector = '.' + itemClass;
                console.log({msg: 'Binding update called for 1st time, initializing Masonry', options: masonryOptions});
                $container.masonry(masonryOptions);
            }
            else {
                console.log({ msg: 'Binding update called again, appending to Masonry', elements: newNodes });
                var newElements = $(newNodes);
                $container.masonry('appended', newElements);
                $container.masonry('layout');
                newNodes.splice(0, newNodes.length); // reset back to empty
            }

            // Update gets called upon initial rendering as well
            haveInitialized = true;
            return { controlsDescendantBindings: true };
        }
    };
})();
以下是正在使用的绑定示例:

<div class="grid" data-bind="masonry: {data: blogEntries, masonryOptions: { itemClass: 'grid-item', columnWidth: 320, gutter: 10}}">
    <div class="grid-item">
        <div data-bind="css: {'idea-blog': isIdea }">
            <img data-bind="attr: { src: imageUrl }">
            <h2 data-bind="text: title"></h2>
            <p data-bind="text: description"></p>
            <div class="button-keep-reading">
                <a data-bind="attr: { src: articleUrl }"><span data-bind="text: linkText"></span> &gt;</a>
            </div>
        </div>
    </div>
</div>

请注意,您需要确保在绑定数据之前加载在砌石平铺中使用的任何图像,因为砌石在其他方面存在布局问题