【问题标题】:Knockout.js custom binding for slideshow: images not displayed幻灯片的 Knockout.js 自定义绑定:图像未显示
【发布时间】:2014-04-18 01:45:22
【问题描述】:

我正在构建带有上一个和下一个按钮的图像幻灯片。图像是从 json 对象中获取的。使用<img data-bind="attr: { src: images } /> 时图像显示正常,没有任何问题,但一旦我应用return { controlsDescendantBindings: true },图像就会停止显示。 <img data-bind="attr: { src: images } /> 上的数据绑定不再起作用。

你知道发生了什么吗?

非常感谢

HTML:

<!-- carousel -->
<div class="carousel" data-bind="carousel: true">
    <div class="controls">
        <a href="#" class="prev">Prev</a>
        <a href="#" class="next">Next</a>
    </div>
    <div class="viewport">
        <!-- trip() represent the json object, but it's confidential -->
        <ul data-bind="foreach: trip().boat.decks">
            <li><a href="#"><img class="image" data-bind="attr: { src: images }" /></a></li>
        </ul>
    </div>
 </div>
 <!-- carousel -->

淘汰赛/JS:

// binding for carousel
ko.bindingHandlers.carousel = {
    init: function (element, valueAccessor) {
        var $carousel = $(element),
            $viewport = $carousel.find('.viewport'),
            $controls = $carousel.find('.controls'),
            $prev = $controls.find('.prev'),
            $next = $controls.find('.next'),
            $slideList = $viewport.find('ul'),
            $slide = $slideList.find('li');

        console.log('carousel starting...');
        console.log('what is element: ', element);
        console.log('what is $element: ', $(element));

        // put active on 1st slide
        $slide.first().addClass('active');

        //TODO: prev btn
        $carousel.on('click', '.prev', function (e) {
            e.preventDefault();

            console.log('Prev btn carousel clicked!');

            $viewport.find('.active').removeClass('active').prev().addClass('active');

            // if arrived at 1st slide, start again from last slide
            if ($viewport.find('.active').index() < 0) {
                $slide.first().removeClass('active');
                $slide.last().addClass('active');
            }
        });

        //TODO: next btn
        $carousel.on('click', '.next', function (e) {

            e.preventDefault();

            console.log('Next btn carousel clicked!');

            $viewport.find('.active').removeClass('active').next().addClass('active');

            // if arrived at last slide, start again from 1st slide
            if ($viewport.find('.active').index() < 0) {
                $slide.last().removeClass('active');
                $slide.first().addClass('active');
            }
        });

        return {
            controlsDescendantBindings: true
        };
    }
};

【问题讨论】:

  • 如果您希望 Knockout 以正常方式处理子绑定,为什么要返回 controlsDescendantBindings: true

标签: javascript jquery mvvm knockout.js slideshow


【解决方案1】:

当您返回 controlsDescendantBindings: true 时,您告诉 Knockout 不要对子元素执行绑定,这就是不绑定子元素的原因。 documentation on creating custom bindings that control descendant bindings 声明:

通常,使用 controlsDescendantBindings 的绑定还将调用 ko.applyBindingsToDescendants(someBindingContext, element) 以将后代绑定应用于某些修改后的绑定上下文。

但是,在您的情况下,您永远不会调用 ko.applyBindingsToDescendants,因此 Knockout 永远不会绑定子元素。

我不确定您为什么首先尝试控制后代绑定,但如果您希望 Knockout 绑定子元素,您需要删除它或确保调用您 ko.applyBindingsToDescendants

【讨论】:

  • 感谢@robert.westerlund 的回复。我正在使用controlsDescendantBindings: true,因为我想让prevnext 按钮上的click 事件起作用,如果我不使用它,它们将不起作用。除非我对客户绑定的理解偏离了轨道……
  • 即使您想监听子元素上的事件,您也不需要执行 controlsDescendantBindings: true(尽管对于动态添加的元素,您可能应该使用 on父母)。但是,我可能会使用 view model and template version 或使用现有 jQuery UI 插件或类似插件来创建实际轮播的 bindingHandler 来制作您的轮播。
  • 感谢@robert.westerlund 的建议。我是 Knockout 的初学者,所以我不太了解自定义绑定
  • 您也可以将其设为self contained bindingHandler,但我仍然建议创建一个使用现有 jQuery UI 轮播插件或类似插件的 bindingHandler。至少,如果您确实创建了一个 bindingHandler,请尽量减少它对拥有完全正确的子 DOM 元素的依赖,如果它依赖于那些,则 bindingHandler 应该自己创建这些子元素,而不是要求 bindingHandler 的用户了解预期的确切结构。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-04-04
  • 2013-09-09
  • 2021-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多