Slick.js 带有 Knockout 自定义绑定的轮播

Slick.js carousel with Knockout custom binding

我想使用漂亮的旋转木马(http://kenwheeler.github.io/slick/) with Knockout. After looking at some of the other questions () it seems like the way to go would be to use a custom binding, but I'm having trouble getting it to load properly - it seems like the slick carousel is initializing before the DOM has completely loaded so it doesn't connect the last slide to the first slide. I also looked at knockout js custom binding called after internal dom elements rendered 并且正在尝试使用子绑定上下文让自定义绑定强制子元素先绑定。

这是 html 标记:

<div data-bind = "slick">
    <!-- ko foreach: results -->
      <div>
        <result-thumbnail params="result:$data"></result-thumbnail>
      </div>
    <!-- /ko -->
</div>

result-thumbnail 是一个单独的剔除组件,用于格式化我想在轮播中呈现的数据。在自定义绑定文件中:

ko.bindingHandlers.slick = {
init: function(element, valueAccessor, allBindingsAccessor, data, bindingContext) {
    var options = {
        infinite:true,
        slidesToShow: 3,
        slidesToScroll: 1,
    };

    var childBindingContext = bindingContext.createChildContext(
        bindingContext.$rawData, 
        null, 
        function(context) {
            ko.utils.extend(context, valueAccessor());
        });
    ko.applyBindingsToDescendants(childBindingContext, element);

    var local = ko.utils.unwrapObservable(valueAccessor());
    ko.utils.extend(options, local);
    $(element).slick(options);
    return { controlsDescendantBindings: true };
},
update: function(element, valueAccessor, allBindingsAccessor, data, context) {
  }
};

我正在考虑的几件事: - 我应该将光滑的初始化移动到更新功能吗? - 我编写的巧妙的自定义绑定是否需要绑定到不同的元素? - 如果我正在更改 results observable 的值,我是否需要通过破坏然后重新创建轮播来更新 slick?

如有任何帮助,我们将不胜感激!我仍在学习自定义绑定,如果有人有过让 slick carousel 与 Knockout 一起工作的经验,那也很高兴听到。

免责声明:我从未使用过slick.js。

您认为轮播在 DOM 完全加载之前正在初始化是正确的。

如果您在 Whosebug 上搜索,您会发现许多关于如何在所有元素都完成渲染后调用函数的选项 - 我最喜欢的选项如下所述:.

一旦你有了这样的回调,你就可以使用它在你的主 viewModel 中设置一个 observable 为 true,像这样:

var allElementsRendered = ko.observable(false);
var yourAfterRenderFunction = function () {
    allElementsRendered(true);
}

然后您可以将该可观察对象作为参数传递给您的 'slick' 绑定,如下所示:

<div data-bind = "slick: allElementsRendered">

每当 allElementsRendered() 可观察值发生变化时,将调用自定义绑定中的 'update' 函数 - 因此只需将初始化逻辑移动到那里,如下所示:

    update: function(element, valueAccessor, allBindingsAccessor, data, context) {
        var shouldInit = ko.unwrap(valueAccessor());

        if (shouldInit) {
            var options = {
                infinite:true,
                slidesToShow: 3,
                slidesToScroll: 1,
            };

            $(element).slick(options);
        } else {
            $(element).slick("unslick");
        }
    }

处理更新结果 observableArray 可能需要一些额外的工作 - 您可以做的是订阅它并在它发生变化时将 allElementsRendered() 设置为 false,如下所示:

var resultsSubscription = results.subscribe(function(newValue){
    allElementsRendered(false);
})

这与上面提到的 afterRenderFunction 相结合应该有望使您的旋转木马保持更新。