Как использовать jQuery в шаблоне Knockout.js?

Я пытаюсь настроить таргетинг на элемент, используя jQuery, который встроен в один из моих шаблонов выбивки:

<script type="text/html" id="video-file-template">
    <div class="video" data-bind="attr: { 'data-index': $index }">
    </div>
</script>

Тем не менее, когда я пытаюсь выбрать $('.video') используя jQuery, завернутый в функцию готовности документа, я получаю объект с возвращаемой длиной 0:

$(document).ready(function() {
    console.log($('.video')); // Returns an object with a length of 0
});

Почему это? Это потому, что элемент не является частью DOM, когда мой скрипт jQuery оценивается? Если это так, как я могу нацелить элемент, когда он загружается в DOM через Knockout.js?

2 ответа

Это правда, что документ уже готов ko.applyBindings заканчивается, поэтому вы не видите элемент. Тем не менее, вы не должны использовать jQuery для нарушения границы между вашей моделью представления и DOM. В нокауте, способ выполнить то, что вам нужно, с помощью пользовательских привязок.

По сути, вы определяете новую привязку нокаута (например, текст, значение, foreach и т. Д.), И у вас есть доступ к init функция, которая запускается при первом отображении элемента, и update функция, которая запускается при обновлении значения, передаваемого в привязку. В вашем случае вам нужно будет только определить init:

ko.bindingHandlers.customVideo = {
    init: function (element) {
        console.log(element, $(element));  // notice you can use jquery here
    }
};

И тогда вы используете привязку, как это:

<div data-bind="customVideo"></div>

Возможно, лучше добавить класс video и выполнить другую инициализацию прямо в обратном вызове init:

ko.bindingHandlers.customVideo = {
    init: function (element) {
        $(element).addClass('video');
    }
};

Если это поначалу кажется немного странным, помните, что есть очень веская причина для косвенного обращения. Он сохраняет вашу модель представления отдельно от DOM, к которой он относится. Таким образом, вы можете менять DOM более свободно и тестировать модель представления более независимо. Если вы ждали ko.applyBindings чтобы закончить и вызвать некоторые вещи jQuery после этого, вам будет сложнее протестировать этот код. Обратите внимание, что выбиваемые пользовательские привязки никоим образом не являются "специальными", и вы можете видеть, что встроенные привязки определены точно так же: https://github.com/knockout/knockout/tree/master/src/binding/defaultBindings

Как указывалось в предыдущих комментариях, это происходит потому, что ваш $(document).ready срабатывает до того, как ваши шаблоны выбывания были обработаны.

Всякий раз, когда мне нужно сделать что-то подобное, я склонен иметь функцию 'init' (или любую другую) в моей модели ko view, которую я вызываю после завершения applyBindings;

Так:

var ViewModel = function(){
     var self=this;
     //blah
     self.init = function(){
         //jquery targeting template elements
     }
}
var vm = new ViewModel();
ko.applyBindings(vm);
vm.init();
Другие вопросы по тегам