我有这段代码。
<img data-bind="attr: {src: 'imagePath'}, style: { 'background-image': 'url('imagePath')' }" class="img-responsive">
问题是它显示两个图像。一个是来自src
的图像和来自background
图像的另一个图像。我的目标是在background
图片不可用时启用src
图片。
答案 0 :(得分:8)
您可以做的是创建自定义绑定,让我们称之为safeSrc
。
在此绑定中,您会收听图片的load
和error
事件 - 如果图片已成功加载,则会对其进行渲染,如果图像不成功,则会进行回退。
在实践中,它可能如下所示:
ko.bindingHandlers.safeSrc = {
update: function(element, valueAccessor) {
var options = valueAccessor();
var src = ko.unwrap(options.src);
$('<img />').attr('src', src).on('load', function() {
$(element).attr('src', src);
}).on('error', function() {
$(element).attr('src', ko.unwrap(options.fallback));
});
}
};
然后,您可以像这样应用绑定:
<img alt="Foo" data-bind="safeSrc: {src: imageObservable, fallback: 'https://example.com/fallback.png'}" />
请注意,这假设您使用的是jQuery - 但您可以轻松地重写事件监听器。
最后,我还想说你应该渲染一个不同的src
而不是背景图片 - 除非你有特殊的理由需要一个?
无论哪种方式,您只需将行$(element).attr('src', ko.unwrap(options.fallback));
更改为$(element).css('background-image', 'url(' + ko.unwrap(options.fallback) + ')');
。
在这里,您可以看到所有内容:https://jsfiddle.net/13vkutkv/2/
(编辑:我用Placehold.it将厚脸皮的热链接替换为Knockout JS徽标)
PS:根据您希望以后与元素交互的方式(与绑定交互/更新绑定),您可能希望使用applyBindingsToNode
(即Knockout-way),而不是操纵{{ 1}}直接在DOM元素上进行属性。
答案 1 :(得分:0)
要显示替代图像,如果找不到img src,请在服务器逻辑中创建备用图像链接,并仅使用src:&#39; imagePath&#39;在你的前端
或者如果在前端执行它很重要,你应该看一下这篇文章: Display alternate image
答案 2 :(得分:0)
我总是用延迟对象检查我的图像,以确保它们会加载。这是使用jquery延迟方法,但您可以使用任何延迟库。我是从内存中编码的,所以可能会有一些错误。
<img data-bind="attr: {src: $root.imagePath()}, style: { 'background-image': 'url('imagePath')' }" class="img-responsive">
var myController = function()
{
var self = this;
this.imagePath = ko.observable('myPath.png'); // Make the image url an observable
var getImagePath = function(path)
{
var imagePath = this.imagePath();
isLoaded(imagePath).done(function(result)
{
// The image will load fine, do nothing.
}).fail(function(e)
{
self.imagePath('defaultImageOnFail.png'); // replace the image if it fails to load
});
};
getImagePath();
};
var isLoaded = function(img)
{
var deferred = new $.Deferred();
var imgObj = $("<img src='"+img+"'/>");
if(imgObj.height > 0 || imgObj.width > 0)
{
deferred.resolve(true);
}
else
{
imgObj.on("load", function(e)
{
deferred.resolve(true);
});
imgObj.on("error", function(e)
{
console.info("VoteScreenController.isLoaded URL error");
deferred.reject();
});
}
return deferred.promise();
};