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