Knockout.js 淘汰赛';如果';绑定到';展开';子脚本

Knockout.js 淘汰赛';如果';绑定到';展开';子脚本,knockout.js,Knockout.js,knockoutjsif绑定可用于根据条件显示或隐藏某些HTML 但是,如果在knockout有机会应用绑定之前,浏览器仍将“查看”并解析绑定中的任何内容。如果内容是图像,则浏览器可能会下载该图像,即使它会立即隐藏 这在移动设备上可能是一个问题 我意识到解决这个问题的一种方法是在图像标记上使用数据绑定,它在knockout运行绑定之前不会设置源: <img data-bind="attr: {'src': .....}"/> 浏览器将忽略脚本标记,因此在应用绑定并呈现模板实例之前

knockoutjs
if
绑定可用于根据条件显示或隐藏某些HTML

但是,如果在knockout有机会应用绑定之前,浏览器仍将“查看”并解析
绑定中的任何内容。如果内容是图像,则浏览器可能会下载该图像,即使它会立即隐藏

这在移动设备上可能是一个问题

我意识到解决这个问题的一种方法是在图像标记上使用数据绑定,它在knockout运行绑定之前不会设置源:

 <img data-bind="attr: {'src': .....}"/>
浏览器将忽略
脚本
标记,因此在应用绑定并呈现模板实例之前,不会下载图像

这很好,但我觉得有点不对劲

我真正想做的是,使用一个新的绑定,自动从脚本标记中打开模板,这样做要简单得多:

 <!-- ko if2: model.banner() == 'cat' -->

    <script type="text/html">
        <figure>
            <img src="https://largeimages.com/cat.jpg" width="1920" height="1080">
        </figure>
    </script>

 <!-- /ko -->

或者,这可能更短:

    <script type="text/html" data-bind="if2: model.banner() == 'cat'">
        <figure>
            <img src="https://largeimages.com/cat.jpg" width="1920" height="1080">
        </figure>
    </script>

我只是没有足够的击倒技巧来编写
if2
绑定,而且我真的以为其他人已经这么做了


因此,如果有人已经这样做了,或者做起来相对简单,我认为这将非常有用。

使用ko模板实际上是一个好主意,尽管它更可能用于呈现您反复使用的html的某些部分,而不是一次。Being说,我会使模板更通用(我想你可能也希望对其他图像使用类似的模板),因此它接受一个js类,在本例中表示一个图像

function AnimalImage(){
    var self = this;
    self.imageUrl = null;
    // plus any other attributes you may want to specify for the image

    self.init = function(imageUrl){
        self.imageUrl = imageUrl;
    }
} 

<script type="text/html" id="animal_header">
    <figure>
        <img data-bind="attr: {'src': imageUrl}" width="1920" height="1080">
    </figure>
</script>
或者多次使用单个对象的模板

<div data-bind='template: { name: 'animal_header', data: cat }'>                                       
</div>
<div data-bind='template: { name: 'animal_header', data: chicken }'>                                       
</div>

在回答之前:我真的不认为需要这样的标记。但我会尽力帮助你,不会质疑你为什么要按照你所描述的那样做:

要使用的标记如下所示:

<script type="text/html" data-bind="if2: model.banner() == 'cat'">
    <figure>
        <img src="https://largeimages.com/cat.jpg" width="1920" height="1080">
    </figure>
</script>
二,。将脚本节点的内容复制到虚拟div

三,。使用虚拟div而不是脚本节点应用原始绑定

四,。将虚拟div注入DOM并去掉脚本节点

五,。收尾

一个(希望如此)可行的例子:

ko.bindingHandlers.if2={
init:函数(元素、valueAccessor、allBindings、viewModel、bindingContext){
var=false;
ko.computed(函数(){
如果(!initialized&&ko.unwrap(valueAccessor())){
var scriptTag=元素;
var replacementDiv=document.createElement(“div”);
replacementDiv.innerHTML=scriptTag.innerHTML;
ko.bindingHandlers.if.init.call(null、replacementDiv、valueAccessor、allBindings、viewModel、bindingContext);
scriptTag.parentElement.replaceChild(replacementDiv,scriptTag);
初始化=真;
}
},空{
删除时处理:元素
});
返回{
ControlsDescentBindings:true
};
}
}
ko.applyBindings({
切换:ko.可观察(假)
})
img{
最大宽度:300px
}


切换(toggle)
这是一个非常古老的方法,但是如果您只想在呈现绑定之前隐藏内容,则不需要将其隐藏在一次性模板中


相反,把你藏的东西放在一个盒子里。在应用敲除绑定之前,它不会显示。

为了避免这种情况,您还可以绑定src属性,在默认情况下添加“#”和显示图像时的实际url。我理解您希望通过自定义if2绑定实现什么,但我认为这不是一个好主意。实际上,使用模板绑定的想法非常好,只需稍加修改,请参见下面我的答案
self.animals = ko.observableArray();

var cat = new AnimalImage();
cat.init("https://largeimages.com/cat.jpg");
self.animals.push(cat);

var chicken = new AnimalImage();
chicken.init("https://largeimages.com/chicken.jpg");
self.animals.push(chicken);
<div data-bind='template: { name: 'animal_header', data: cat }'>                                       
</div>
<div data-bind='template: { name: 'animal_header', data: chicken }'>                                       
</div>
self.chicken = ko.observable();
self.cat = ko.observable();

var cat = new AnimalImage();
cat.init("https://largeimages.com/cat.jpg");
self.cat(cat);

var chicken = new AnimalImage();
chicken.init("https://largeimages.com/chicken.jpg");
self.chicken(chicken);
<script type="text/html" data-bind="if2: model.banner() == 'cat'">
    <figure>
        <img src="https://largeimages.com/cat.jpg" width="1920" height="1080">
    </figure>
</script>
 init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
  var initialized = false;

  ko.computed(function() { 
    if (!initialized && ko.unwrap(valueAccessor())) {
      var scriptTag = element;
      var replacementDiv = document.createElement("div");
      replacementDiv.innerHTML = scriptTag.innerHTML;
      ko.bindingHandlers.if.init.call(null, 
        replacementDiv, valueAccessor, allBindings, viewModel, bindingContext);
      scriptTag.parentElement.replaceChild(replacementDiv, scriptTag);
      initialized = true;
    }
  }, null, { disposeWhenNodeIsRemoved: element });

  return { controlsDescendantBindings: true };
}