Не работает привязка нокаута для slick js
Мой рабочий код без привязки нокаута:
<div class="slick_demo_1">
<div>
<div class="ibox-content">
<h2>Slide 1</h2>
</div>
</div>
<div>
<div class="ibox-content">
<h2>Slide 2</h2>
</div>
</div>
<div>
<div class="ibox-content">
<h2>Slide 3</h2>
</div>
</div>
</div>
И чтобы инициализировать пятно мой код JS:
$('.slick_demo_1').slick({
dots: true
});
Код выше работает нормально. Теперь код с привязкой нокаута:
<div class="slick_demo_1" data-bind="foreach:showSlider">
<div>
<div class="ibox-content">
<h2 data-bind="slider"></h2>
</div>
</div>
</div>
И чтобы связать пятно с DOM мой код:
ko.bindingHandlers.slick = {
init: function (element, valueAccessor) {
$(element).slick({
dots: true
});
}
};
Но пользовательская привязка не работает. Что я делаю не так?
1 ответ
Код, который вы показываете, почти не похож на правильную реализацию пользовательского связующего.
Несколько подсказок:
- вы должны использовать пользовательскую привязку в корневом элементе
- пользовательская привязка должна заботиться о создании и, если возможно, удалении API карусели из элемента (используя slick's
destroy
или жеunslick
) если элемент утилизируется - пользовательское связующее должно иметь возможность обновлять элементы внутри карусели
- было бы интересно использовать дополнительный
slickOptions
привязка для передачи дополнительных объектов в гладкую инициализацию
Базовая структура пользовательского связывания объясняется здесь. Смотрите шаблон кода:
ko.bindingHandlers.yourBindingName = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
// This will be called when the binding is first applied to an element
// Set up any initial state, event handlers, etc. here
},
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
// This will be called once when the binding is first applied to an element,
// and again whenever any observables/computeds that are accessed change
// Update the DOM element based on the supplied values here.
}
};
Как объяснено, init
отвечает за инициализацию карусели, а update
отвечает за обновление содержимого карусели при изменении массива. R P Niemeyer дает подробное объяснение пользовательской привязки здесь: Другой взгляд на пользовательские привязки для KnockoutJS.
Если вы реализуете это правильно, ваш HTML-код должен выглядеть примерно так:
<div data-bind="slick: imagesArray, slickOptions: additionalOptions>
</div>
На init
Ваша пользовательская привязка должна создавать элементы на основе imagesArray
и вызвать гладкую инициализацию, используя additionalOptions
если присутствует, и зарегистрируйте скользкое разрушение, когда элемент утилизируется с помощью ko. В обновлении вы должны изменить внутренние элементы и по возможности повторно применить слик. Вам также следует ознакомиться с API Slick.
Эта скрипка показывает частичную реализацию, но более полную, чем текущий фрагмент кода:
var imageUrls = [];
var i = 1;
for (i=1;i<=10;i++)
imageUrls.push('http://lorempixel.com/400/200/animals/'+i);
ko.bindingHandlers.slick = {
init: function(element, valueAccessor, allBindingsAccessor) {
// Clears the div
$(element).empty();
// Creates the inner divs with images
var images = ko.unwrap(valueAccessor());
if (images) {
images.forEach(function(imgUrl) {
$div = $('<div>');
$image = $('<img>');
$image.attr('src',imgUrl);
$div.append($image);
$(element).append($div)
});
}
// try to recover slickOptions
var options = allBindingsAccessor().slickOptions || {};
// Initialize slick on the div, with provided options
$(element).slick(options);
//handle disposal, if KO removes the element
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
$(element).slick('unslick');
});
},
//update the control when the view model changes
update: function(element, valueAccessor) {
var images = ko.unwrap(valueAccessor());
// Do something to update the content
}
};
var vm = {
images: ko.observableArray(imageUrls),
options: {}
}
ko.applyBindings(vm, gallery);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/jquery.slick/1.5.8/slick.min.js"></script>
<link href="https://cdn.jsdelivr.net/jquery.slick/1.5.8/slick.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/jquery.slick/1.5.8/slick-theme.css" rel="stylesheet">
<div id="gallery"
style="width:400px"
data-bind="slick: images, slickOptions: {dots:true, initialSlide:4}">
</div>
Отсутствующая часть в реализации - обновление галереи, если изменяется imgUrls. Но он показывает основные приемы в подсказках.