Карусель Slick.js с пользовательской привязкой Knockout
Я хотел использовать потрясающую гладкую карусель ( http://kenwheeler.github.io/slick/) с Knockout. После рассмотрения некоторых других вопросов ( https://stackru.com/questions/26368176/slick-js-carousel-not-working-with-knockout-template-binding) кажется, что путь будет заключаться в использовании пользовательская привязка, но у меня возникают проблемы с ее правильной загрузкой - похоже, что гладкая карусель инициализируется до полной загрузки DOM, поэтому последний слайд не соединяется с первым слайдом. Я также посмотрел на пользовательскую привязку knockout js, вызываемую после рендеринга внутренних элементов dom, и пытаюсь использовать контексты дочерней привязки, чтобы пользовательская привязка заставляла дочерние элементы сначала связываться.
Вот 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
Можно ли обновить пятно, уничтожив и воссоздав карусель?
Любая помощь будет оценена! Я все еще изучаю пользовательские привязки, и если у кого-то был опыт работы с гладкой каруселью для работы с Knockout, было бы здорово услышать и о ней.
1 ответ
Отказ от ответственности: я никогда не использовал slick.js.
Вы правы, полагая, что карусель инициализируется до полной загрузки DOM.
Если вы выполняете поиск в stackru, вы найдете много опций о том, как вызывать функцию, когда все элементы закончили рендеринг - тот, который мне нравится больше всего, описан здесь: /questions/31569065/nokaut-posle-rendera-no-tolko-odin-raz/31569086#31569086.
Если у вас есть такой обратный вызов, вы можете использовать его для установки наблюдаемой в вашей основной viewModel true
, как это:
var allElementsRendered = ko.observable(false);
var yourAfterRenderFunction = function () {
allElementsRendered(true);
}
Затем вы можете передать это наблюдаемое в качестве параметра вашей "гладкой" привязке, например так:
<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, должно поддерживать вашу карусель в актуальном состоянии.