Javascript 加载后:检查图像是否在浏览器缓存中
简短版问题: 是否有navigator.mozislocally在所有浏览器上都可用的等效函数,或其他替代函数 长版本:) 嗨, 以下是我的情况: 我想为asp.net MVC实现一个HtmlHelper扩展,它可以轻松地处理图像后期加载(使用jQuery) 因此,我使用“alt”属性中指定的空图像源呈现页面。 我在“window.onload”事件之后插入了图像源,效果非常好 我是这样做的:Javascript 加载后:检查图像是否在浏览器缓存中,javascript,jquery,caching,lazy-loading,Javascript,Jquery,Caching,Lazy Loading,简短版问题: 是否有navigator.mozislocally在所有浏览器上都可用的等效函数,或其他替代函数 长版本:) 嗨, 以下是我的情况: 我想为asp.net MVC实现一个HtmlHelper扩展,它可以轻松地处理图像后期加载(使用jQuery) 因此,我使用“alt”属性中指定的空图像源呈现页面。 我在“window.onload”事件之后插入了图像源,效果非常好 我是这样做的: $(window).bind('load', function() { var plImage
$(window).bind('load', function() {
var plImages = $(".postLoad");
plImages.each(function() {
$(this).attr("src", $(this).attr("alt"));
});
});
问题是:第一次加载后,会缓存加载后的图像。但是,如果加载页面需要10秒,则缓存的加载后图像将在这10秒后显示
因此,如果图像被缓存以立即显示,我认为应该在“document.ready”事件中指定图像源
我发现这个函数:navigator.mozislocally可用于检查缓存中是否有图像。以下是我对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:结果相同
还有其他选择吗?如果缓存了图像,则对图像的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;
}
var lqueue=[];
$(函数(){
var t,ac=0;
(t=$(“img”)。每个(
功能(即,e)
{
var rq=$.ajax(
{
是的,
键入:“获取”,
async:true,
网址:e.alt,
成功:function(){var rq3=rq;if(rq3.readyState==4){e.src=e.alt;},
错误:函数(){e.src=e.alt;}
});
setTimeout(函数()
{
变量k=i,e2=e,r2=rq;
如果(r2.readyState!=4)
{
r2.中止();
lqueue.push(e2);
}
如果(t.length==(++ac))loadRequeue();
}, 0);
}
);
});
函数loadRequeue()
{
对于(var j=0;j
经过研究,我找到了一个解决方案:
其思想是记录缓存的图像,在图像“加载”事件上绑定一个日志函数。
我首先想到将数据源存储在cookie中,但如果在没有cookie的情况下清除缓存,则不可靠。此外,它还向HTTP请求添加了一个cookie
然后我遇到了魔法:window.localStorage()
localStorage属性提供
域的持久存储区域
正是我想要的:)。这个属性在HTML5中是标准化的,并且它已经在几乎所有最近的浏览器(FF、Opera、Safari、IE8、Chrome)上运行
以下是代码(不处理window.localStorage不兼容的浏览器):
var storage=window.localStorage;
if(!storage.cachedElements){
storage.cachedElements=“”;
}
函数logCache(源){
if(storage.cachedElements.indexOf(source,0)<0){
if(storage.cachedElements!=“”)
storage.cachedElements+=“;”;
storage.cachedElements+=源;
}
}
缓存的函数(源){
返回(storage.cachedElements.indexOf(source,0)>=0);
}
变异图像;
//关于DOM Ready
$(文档).ready(函数(){
plImages=$(“.postLoad”);
//日志缓存图像
plImages.bind('load',function()){
logCache($(this.attr(“src”));
});
//显示缓存的图像
plImages.each(function(){
var source=$(this.attr(“alt”)
if(缓存(源))
$(this.attr(“src”,来源);
});
});
//页面加载后
$(窗口).bind('load',function(){
//显示未缓存的图像
plImages.each(function(){
if($(this.attr(“src”)=“”)
$(this.attr(“src”),$(this.attr(“alt”);
});
});
我对您的空图像源有一点意见。你写道:
因此,我使用“alt”属性中指定的空图像源呈现页面。我在“window.onload”事件之后插入了图像源,效果非常好
我在过去遇到过这个问题,因为在一些浏览器中,空的src
属性会导致额外的请求。以下是他们所做的(抄袭自,还有一篇关于该问题的详细报道):
- Internet Explorer向页面所在的目录发出请求
- Safari和Chrome向实际页面本身发出请求
- Firefox3和早期版本的行为与Safari和Chrome相同,但版本3.5解决了这个问题[bug 444931],不再发送请求
- 遇到空图像src时,Opera不会执行任何操作
src=“t.gif”
用于我仅在页面加载后插入的图像。它非常小,由浏览器缓存。这对我们来说非常有效
干杯,奥利弗,以防其他人遇到同样的问题。这里提供的一些解决方案(即将缓存信息存储在本地浏览器数据存储器中)可能因两个原因而中断。首先,如果图像的缓存过期,其次,如果用户清除了缓存。另一种方法是将图像源设置为占位符。然后将源更改为图像路径/名称。这样,浏览器就有责任检查自己的缓存。应该适用于大多数浏览器,无论其API如何 2017年,资源计时API可以帮助您使用PerformanceResourceTiming.transferSize属性检查这一点。从服务器下载(未缓存)时,此属性应返回非零传输大小,如果从本地缓存获取,则返回零
参考资料:检查图像
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"));
});
});
function isCached(src) {
var img = new Image();
img.src = src;
var complete = img.complete;
img.src = "";
return complete;
}
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}
/>
)
}