简短版本问题: 是否有navigator.mozIsLocallyAvailable等效函数适用于所有浏览器,还是替代?
长版:)
您好, 这是我的情况: 我想为asp.net MVC实现一个HtmlHelper扩展,它可以轻松处理图像后加载(使用jQuery)。
所以我使用“alt”属性中指定的源渲染具有空图像源的页面。 我在“window.onload”事件之后插入图像源,效果很好。
我做了类似的事情:
$(window).bind('load', function() {
var plImages = $(".postLoad");
plImages.each(function() {
$(this).attr("src", $(this).attr("alt"));
});
});
问题是:首次加载后,缓存后载图片。但是如果页面加载需要10秒钟,则在此10秒后将显示缓存的后载图像。
所以我想在“document.ready”事件中指定图像源,如果图像被缓存以立即显示它们。
我找到了这个函数:navigator.mozIsLocallyAvailable可以检查图像是否在缓存中。这是我用jquery做的事情:
//specify cached image sources on dom ready
$(document).ready(function() {
var plImages = $(".postLoad");
plImages.each(function() {
var source = $(this).attr("alt")
var disponible = navigator.mozIsLocallyAvailable(source, true);
if (disponible)
$(this).attr("src", source);
});
});
//specify uncached image sources after page loading
$(window).bind('load', function() {
var plImages = $(".postLoad");
plImages.each(function() {
if ($(this).attr("src") == "")
$(this).attr("src", $(this).attr("alt"));
});
});
它适用于Mozilla的DOM,但它不适用于任何其他DOM。我试过navigator.isLocallyAvailable:结果相同。
还有其他选择吗?
答案 0 :(得分:17)
这个想法是记录缓存的图像,在图像'load'事件上绑定日志功能。 我首先想过将源存储在cookie中,但如果在没有cookie的情况下清除缓存则不可靠。此外,它还为HTTP请求添加了一个cookie ...
然后我遇到了魔法: window.localStorage (details)
localStorage属性提供 域的持久存储区域
正是我想要的:)。这个属性在HTML5中标准化,它已经适用于几乎所有最近的浏览器(FF,Opera,Safari,IE8,Chrome)。
这是代码(不处理window.localStorage不兼容的浏览器):
var storage = window.localStorage;
if (!storage.cachedElements) {
storage.cachedElements = "";
}
function logCache(source) {
if (storage.cachedElements.indexOf(source, 0) < 0) {
if (storage.cachedElements != "")
storage.cachedElements += ";";
storage.cachedElements += source;
}
}
function cached(source) {
return (storage.cachedElements.indexOf(source, 0) >= 0);
}
var plImages;
//On DOM Ready
$(document).ready(function() {
plImages = $(".postLoad");
//log cached images
plImages.bind('load', function() {
logCache($(this).attr("src"));
});
//display cached images
plImages.each(function() {
var source = $(this).attr("alt")
if (cached(source))
$(this).attr("src", source);
});
});
//After page loading
$(window).bind('load', function() {
//display uncached images
plImages.each(function() {
if ($(this).attr("src") == "")
$(this).attr("src", $(this).attr("alt"));
});
});
答案 1 :(得分:5)
如果缓存了图像的ajax请求几乎会立即返回。然后使用setTimeout确定它是否未就绪并取消请求,以便稍后将其重新排队。
<强>更新强>
var lqueue = [];
$(function() {
var t,ac=0;
(t = $("img")).each(
function(i,e)
{
var rq = $.ajax(
{
cache: true,
type: "GET",
async:true,
url:e.alt,
success: function() { var rq3=rq; if (rq3.readyState==4) { e.src=e.alt; } },
error: function() { e.src=e.alt; }
});
setTimeout(function()
{
var k=i,e2=e,r2=rq;
if (r2.readyState != 4)
{
r2.abort();
lqueue.push(e2);
}
if (t.length==(++ac)) loadRequeue();
}, 0);
}
);
});
function loadRequeue()
{
for(var j = 0; j < lqueue.length; j++) lqueue[j].src=lqueue[j].alt;
}
答案 2 :(得分:4)
我对你的空图像来源有一个评论。你写道:
所以我使用“alt”属性中指定的源渲染具有空图像源的页面。我在“window.onload”事件之后插入图像源,效果很好。
我在过去遇到过这个问题,因为在某些浏览器中,空src
属性会导致额外的请求。这是他们的行为(从Yahoo! performance rules复制,在此问题上还有一个blog post更详细的信息):
我们在网站上也使用了很多jQuery,并不总是可以避免空图像标记。我选择使用像这样的1x1 px透明gif:src="t.gif"
用于我仅在pageload之后插入的图像。它非常小,可以通过浏览器进行缓存。这对我们来说非常有效。
干杯,奥利弗
答案 3 :(得分:2)
以防万一其他人可能会遇到同样的问题。这里提供的一些解决方案(即将缓存信息存储在本地浏览器数据存储中)可能会因为两个原因而中断。首先,如果图像的高速缓存到期,则第二,如果用户清除了高速缓存。另一种方法是将图像源设置为占位符。然后将源更改为图像路径/名称。这样,浏览器就有责任检查自己的缓存。适用于大多数浏览器,无论其API如何。
答案 4 :(得分:2)
2017年,Resource Timing API可以帮助您使用PerformanceResourceTiming.transferSize属性进行检查。从服务器(未缓存)下载时,此属性应返回非零传输大小,如果从本地缓存中获取,则返回零。
参考:https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/transferSize
答案 5 :(得分:0)
检查图像是否已被缓存的最有效,最简单且广泛支持的方法是执行以下操作...
像这样...
function is_cached(src) {
var img = new Image();
img.src = src;
var complete = img.complete;
img.src = "";
return complete;
}
答案 6 :(得分:0)
对于任何可能试图用 React 解决这个问题的人,我使用 complete
图像属性在 React 中以这种方式解决它:
import React, { useState, useEffect, useRef } from 'react'
const Component= () => {
const [isLoadedImage, setLoadedImage] = useState(false)
const imageRef = useRef(null)
useEffect(() => {
const imgEl = imageRef.current
if (imgEl && imgEl.complete && !isLoadedImage) setLoadedImage(true)
})
return (
<img
onLoad={() => (!isLoadedImage ? setLoadedImage(true) : null)}
ref={imageRef}
/>
)
}