3

我想在Knockout中使用很棒的圆滑轮播 ( http://kenwheeler.github.io/slick/ )。在查看了其他一些问题(https://stackoverflow.com/questions/26368176/slick-js-carousel-not-working-with-knockout-template-binding)之后,似乎要走的路是使用自定义绑定,但我无法正确加载它 - 看起来光滑的轮播在 DOM 完全加载之前正在初始化,因此它不会将最后一张幻灯片连接到第一张幻灯片。我还查看了在渲染内部 dom 元素后调用的淘汰赛 js 自定义绑定,并尝试使用子绑定上下文让自定义绑定强制子元素首先绑定。

这是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) {
  }
};

我正在考虑的一些事情: - 我应该将光滑的初始化移动到更新功能吗?- 我写的自定义绑定是否需要绑定到不同的元素?- 如果我要更改resultsobservable 的值,我是否需要通过销毁然后重新创建轮播来更新 slick?

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

4

1 回答 1

1

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

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

如果您在 stackoverflow 上进行搜索,您会发现许多关于如何在所有元素完成渲染后调用函数的选项——我最喜欢的选项如下所述:https ://stackoverflow.com/a/19941134/3620458 。

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

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

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

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

每当 allElementsRendered() observable 发生变化时,自定义绑定中的“更新”函数就会被调用——所以只需将初始化逻辑移到那里,如下所示:

    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 应该有望使您的轮播保持更新。

于 2015-04-15T20:06:15.583 回答