knockoutjs if
绑定可用于根据条件显示或隐藏某些HTML。
然而,浏览器仍然会看到'并且在挖掘有机会应用绑定之前解析if
绑定内的任何内容。如果内容是图像,则即使将立即隐藏该图像,也可以由浏览器下载该图像。
这可能是移动设备上的问题。
我意识到解决这个问题的一种方法是在图像标签上使用数据绑定,这不会设置源,直到knockout运行绑定:
<img data-bind="attr: {'src': .....}"/>
出于这个问题的目的,我不想这样做(内容比单个图像复杂得多)。所以另一种解决方案是在 if
绑定中使用模板绑定,如下所示:
<!-- ko if: model.banner() == 'cat' -->
<script type="text/html" id="cat_header">
<figure>
<img src="https://largeimages.com/cat.jpg" width="1920" height="1080">
</figure>
</script>
<!-- ko template: { name: 'cat_header' } --><!-- /ko -->
<!-- /ko -->
浏览器会忽略script
标记,因此图像不会被下载,直到应用绑定并呈现模板实例。
这很好用,但我觉得有点笨拙。
我真正喜欢做的事情是使用新的绑定更简单的方法,该绑定会自动从脚本标记中解开模板:
<!-- 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
绑定,而且我真的以为其他人已经做过了。
所以,如果有人已经这样做了,或者做起来相对简单,我认为它会非常有用。
答案 0 :(得分:1)
使用ko模板实际上是一个好主意,尽管它应该更有可能用于渲染重复使用的html的某些部分,而不仅仅是一次。那个说法,我会使模板更通用(我想你也可能想要为其他图像使用类似的模板),所以它接受一个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>
然后,如果您想要显示多个图像,可以在模板绑定中使用'foreach'参数,该参数接受与模板绑定的对象的observableArray
<div data-bind='template: { name: 'animal_header', foreach: animals }'>
</div>
在viewmodel中
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>
在viewmodel中
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);
答案 1 :(得分:0)
在回答之前:我并不真正看到需要这样的标记。但我会尝试提供帮助,而不会质疑为什么你想要按照你所描述的那样去做:
您要使用的标记是:
<script type="text/html" data-bind="if2: model.banner() == 'cat'">
<figure>
<img src="https://largeimages.com/cat.jpg" width="1920" height="1080">
</figure>
</script>
浏览器不会查看内容,但是淘汰将应用数据绑定到这种类型的节点:一个良好的开端。
我认为我们尝试做的事情归结为:
if
绑定值返回true
后,替换div的脚本标记if
数据绑定。所以我编写了一个自定义绑定处理程序来完成这两件事。
1。等到绑定的值第一次返回true:
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var initialized = false;
ko.computed(function() {
if (!initialized && ko.unwrap(valueAccessor())) {
2。将脚本节点的内容复制到虚拟div
var scriptTag = element;
var replacementDiv = document.createElement("div");
replacementDiv.innerHTML = scriptTag.innerHTML;
3。将原始绑定应用于我们的虚拟div而不是脚本节点
ko.bindingHandlers.if.init.call(null,
replacementDiv, valueAccessor, allBindings, viewModel, bindingContext);
4。将虚拟div注入DOM并删除脚本节点
scriptTag.parentElement.replaceChild(replacementDiv, scriptTag);
5。总结
initialized = true;
}
}, null, { disposeWhenNodeIsRemoved: element });
return { controlsDescendantBindings: true };
}
一个(希望)工作的例子:
ko.bindingHandlers.if2 = {
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
};
}
}
ko.applyBindings({
toggled: ko.observable(false)
})
&#13;
img {
max-width: 300px
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script type="text/html" data-bind="if2: toggled">
<img src="https://upload.wikimedia.org/wikipedia/commons/4/4d/Cat_March_2010-1.jpg">
</script>
<div data-bind="text: toggled"></div>
<button data-bind="click: toggled.bind(null, !toggled())">toggle</button>
&#13;
答案 2 :(得分:0)
这是永远古老的方法,但是如果您只想隐藏内容直到呈现绑定,那么就不需要将其隐藏在一次性模板中。
相反,只需将您隐藏的内容放在中即可。在应用剔除绑定之前,它不会显示。