这些是foreach循环:
<!-- ko foreach: {data: categories,as: 'categories'} --> <!-- Category code --> <!-- ko foreach: {data: visibleStations,as: 'stations'} --> <!-- specific code --> <img class="thumb lazy" data-bind="attr: { src: imageTmp,'data-src': imageThumb,alt: name,'data-original-title': name },css: {'now-playing-art': isPlaying}"> <!-- /ko --> <!-- /ko -->
所以基本上当我创建这些元素时,imageTmp是一个计算的observable,它返回一个临时url,并且imageThumb被设置为一个来自CDN的真正的url.
而且我也有这块代码,叫这个Lazy Sweeper:
var lazyInterval = setInterval(function () { $('.lazy:in-viewport').each(function () { $(this).attr('src',$(this).data('src')).bind('load',function(){ $(this).removeClass('lazy') }); }); },1000);
该代码去查找视口中的这些图像(使用自定义选择器仅在屏幕上查找图像),然后将src设置为data-src.
我们想要的行为是避免加载用户不会看到的千兆(呃实际上是几百)的开销.
我们看到的行为是,在第一次加载时,看起来像ko.applyBindings()被称为某种程度上的懒惰扫描器被弄脏,我们看到图像恢复到默认图像.然后清扫员重新运行,我们再次看到它们显示.
我们不清楚如何以更具有挑战性的方式实现这一点.
思考?见解?想法?
我在twitter上得到一个答案,提到一个不同的lazyloading图书馆.这并没有解决这个问题 – 问题不在于DOM和ko表示方式需要如何进行交互才能建立起来.我相信我需要的是一个更好的方法来考虑创建一个设置imageTmp的敲门模型的问题,并根据是否在视口中响应懒惰,然后在加载imageThumb(真实图像)后更新模型.
解决方法
我的做法是:
>让你的模型(站)决定图像的URL是临时还是真实的,就像你已经做到的那样
>有一个绑定,其工作是处理DOM – 设置图像源和处理加载事件
>限制懒惰扫帚只是提供信号“你现在可见”
视图模型
>添加一个包含我们的状态的showPlaceholder标志:
this.showPlaceholder = ko.observable(true);
>添加一个计算的observable,总是返回当前正确的图像url,具体取决于该状态:
this.imageUrl = ko.computed(function() { return this.showPlaceholder() ? this.imageTemp() : this.imageThumb(); },this);
现在我们要做的就是每当图像加载时,将showPlaceholder设置为false.在一分钟内更多的.
绑定
我们的绑定工作是设置< img src>每当计算的imageUrl更改时.如果src是真实的图像,它应该在加载后删除懒惰类.
ko.bindingHandlers.lazyImage = { update: function(element,valueAccessor,allBindingsAccessor,viewmodel,bindingContext) { var $element = $(element),// we unwrap our imageUrl to get a subscription to it,// so we're called when it changes. // Use ko.utils.unwrapObservable for older versions of Knockout imageSource = ko.unwrap(valueAccessor()); $element.attr('src',imageSource); // we don't want to remove the lazy class after the temp image // has loaded. Set temp-image-name.png to something that identifies // your real placeholder image if (imageSource.indexOf('temp-image-name.png') === -1) { $element.one('load',function() { $(this).removeClass('lazy'); }); } } };
懒人扫帚
所有这些都需要做的是给我们的视图模型提示它现在应该从占位符切换到真实图像.
ko.dataFor(element)和ko.contextFor(element)helper functions使我们能够访问与外部DOM元素绑定的任何内容:
var lazyInterval = setInterval(function () { $('.lazy:in-viewport').each(function () { if (ko.dataFor(this)) { ko.dataFor(this).showPlaceholder(false); } }); },1000);