如何在Knockout.js模板中使用jQuery?

Rea*_*ues 2 html javascript jquery dom knockout.js

我正在尝试使用嵌入在我的一个淘汰模板中的jQuery来定位元素:

<script type="text/html" id="video-file-template">
    <div class="video" data-bind="attr: { 'data-index': $index }">
    </div>
</script>
Run Code Online (Sandbox Code Playgroud)

然而,当我尝试$('.video')使用jQuery 选择包装在文档就绪函数中时,我得到一个长度为0的对象:

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

为什么是这样?是因为在评估我的jQuery脚本时,该元素不是DOM的一部分?如果是这样,当通过Knockout.js将元素加载到DOM时,如何定位元素?

Mil*_*ric 6

确实,文档在ko.applyBindings完成之前就已经准备就绪,这就是为什么你没有看到这个元素的原因.但是,您不应该使用jQuery来违反视图模型和DOM之间的边界.在淘汰赛中,完成所需内容的方法是使用自定义绑定.

基本上,您定义了一个新的knockout绑定(如text,value,foreach等),并且您可以访问一个init函数,该函数在首次呈现元素时触发,还有一个update函数,当您传递给绑定的值时,该函数将触发更新.在您的情况下,您只需要定义init:

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

然后你使用这样的绑定:

<div data-bind="customVideo"></div>
Run Code Online (Sandbox Code Playgroud)

也许最好添加"video"类并在init回调中进行其他初始化:

ko.bindingHandlers.customVideo = {
    init: function (element) {
        $(element).addClass('video');
    }
};
Run Code Online (Sandbox Code Playgroud)

如果一开始感觉有点不稳定,请记住这是间接的一个很好的理由.它使您的视图模型与它适用的DOM分开.因此,您可以更自由地更改DOM,并且可以更独立地测试视图模型.如果你等到ko.applyBindings完成并在那之后调用了一些jQuery的东西,你将更难以测试该代码.请注意,敲除自定义绑定在任何方面都不是"特殊",您可以看到内置绑定的定义完全相同:https://github.com/knockout/knockout/tree/master/src/binding/defaultBindings