读书人

急chrome对于js的for循环执行有关问题

发布时间: 2014-01-21 00:35:39 作者: rapoo

急急急.....chrome对于js的for循环执行问题
我的问题是:原则上,for循环执行一次,最后这行代码就要立即执行:document.getElementById(shotCol).appendChild(div); IE 和 FF 都是正常的,在每次for循环的时候就立即执行了,但是chrome则不是,chrome是把整个for循环跑完之后(i从0-2),然后才统一执行document.getElementById(shotCol).appendChild(div); 这样导致结果就不一样,请问怎么调整? 我要调整到同IE和FF的那种每次for循环的时候就执行的效果,而不是for循环整个都跑完了才统一执行。

for(var i=0; i<2; i++)
{
var bone,btwo,bthree,shotCol;
bone = document.getElementById("cols1").offsetHeight;
btwo = document.getElementById("cols2").offsetHeight;
bthree = document.getElementById("cols3").offsetHeight;
var div = document.createElement("div");
div.className = "img_box";
div.innerHTML = '<img src="images/'+Math.ceil(Math.random()*7)+'.jpg" width="300px" />';
if(bone - btwo <= 0 && bone - bthree <= 0)
{
shotCol = "cols1";
}
else if(btwo - bone <= 0 && btwo - bthree <= 0)
{
shotCol = "cols2";
}
else
{
shotCol = "cols3";
}
document.getElementById(shotCol).appendChild(div);
}

[解决办法]
没测试代码,看不出什么效果,不过你的是for循环,ie和firefox应该也不可能看到1条加完等待一下在添加另外一条的效果吧,这个执行时间肉眼分辨不出来吧。

要是你要哪种效果,可以用setTimeout延时来执行,不用for语句


    var i = 0;

function addDiv() {
var bone, btwo, bthree, shotCol;
bone = document.getElementById("cols1").offsetHeight;
btwo = document.getElementById("cols2").offsetHeight;
bthree = document.getElementById("cols3").offsetHeight;
var div = document.createElement("div");
div.className = "img_box";
div.innerHTML = '<img src="images/' + Math.ceil(Math.random() * 7) + '.jpg" width="300px" />';
if (bone - btwo <= 0 && bone - bthree <= 0) {
shotCol = "cols1";
}
else if (btwo - bone <= 0 && btwo - bthree <= 0) {
shotCol = "cols2";
}
else {
shotCol = "cols3";
}
document.getElementById(shotCol).appendChild(div);
i++;
if (i < 2) setTimeout(addDiv, 500);////////
}
setTimeout(addDiv, 500);

[解决办法]

div.innerHTML = '<img src="images/' + Math.ceil(Math.random() * 7) + '.jpg" width="300px" />';
//1、改为:
var img = document.createElement("img");
img.style.width="300px";
img.src="images/" + Math.ceil(Math.random() * 7) + ".jpg";
div.appendChild(img);
//2、或者移动到document.getElementById(shotCol).appendChild(div);之后

[解决办法]
把函的量明放到for外面
[解决办法]
引用:
没测试代码,看不出什么效果,不过你的是for循环,ie和firefox应该也不可能看到1条加完等待一下在添加另外一条的效果吧,这个执行时间肉眼分辨不出来吧。

要是你要哪种效果,可以用setTimeout延时来执行,不用for语句


    var i = 0;

function addDiv() {
var bone, btwo, bthree, shotCol;


bone = document.getElementById("cols1").offsetHeight;
btwo = document.getElementById("cols2").offsetHeight;
bthree = document.getElementById("cols3").offsetHeight;
var div = document.createElement("div");
div.className = "img_box";
div.innerHTML = '<img src="images/' + Math.ceil(Math.random() * 7) + '.jpg" width="300px" />';
if (bone - btwo <= 0 && bone - bthree <= 0) {
shotCol = "cols1";
}
else if (btwo - bone <= 0 && btwo - bthree <= 0) {
shotCol = "cols2";
}
else {
shotCol = "cols3";
}
document.getElementById(shotCol).appendChild(div);
i++;
if (i < 2) setTimeout(addDiv, 500);////////
}
setTimeout(addDiv, 500);



如果LZ的意思是lazyload方式进行添加的话,那在#2中showbo已经给出了办法呀
[解决办法]
给你精简一下那个取对象的方法
var bone    =   document.getElementById("cols1").offsetHeight, 
btwo = document.getElementById("cols2").offsetHeight,
bthree = document.getElementById("cols3").offsetHeight,
colList = {},
_min = Math.min.apply(null,[bone,btwo,bthree]);

colList[bone] = 'cols1';
colList[btwo] = 'cols2';
colList[bthree] = 'cols3';

var shotCol = colList[_min],
div = document.createElement("div");

[解决办法]
引用:
Quote: 引用:

版本 31.0.1650.57 m

额 那真实奇怪,我测试的时候也是你这个版本,我现在升级到了 31.0.1650.63 m,也还是这个问题
不过用#2提供的方法确实搞定了看来通用的办法就是setTimeout延迟对迪欧用然后再加载才OK

这个因为chrome是生成html后读图片后再设定高度 所以循环的时候高度为0 settimeout的时候图片没读完估计还是0
[解决办法]
引用:
Quote: 引用:

Quote: 引用:

版本 31.0.1650.57 m

额 那真实奇怪,我测试的时候也是你这个版本,我现在升级到了 31.0.1650.63 m,也还是这个问题
不过用#2提供的方法确实搞定了看来通用的办法就是setTimeout延迟对迪欧用然后再加载才OK

这个因为chrome是生成html后读图片后再设定高度 所以循环的时候高度为0 settimeout的时候图片没读完估计还是0

var img;
var i = 0;
function appendDiv(){
var bone,btwo,bthree,shotCol;
bone = document.getElementById("cols1").offsetHeight;
btwo = document.getElementById("cols2").offsetHeight;
bthree = document.getElementById("cols3").offsetHeight;
var div = document.createElement("div");
div.appendChild(img);
if(bone - btwo <= 0 && bone - bthree <= 0)


{
shotCol = "cols1";
}
else if(btwo - bone <= 0 && btwo - bthree <= 0)
{
shotCol = "cols2";
}
else
{
shotCol = "cols3";
}
document.getElementById(shotCol).appendChild(div)
i++;
if(i<2){
appendImg();
}
}
function appendImg(){
img = new Image();
//img.src = 'images/'+Math.ceil(Math.random()*7)+'.jpg';
img.src = '1.jpg';
img.style.height = "300px";
img.onload = appendDiv
};
appendImg();


[解决办法]
引用:
Quote: 引用:

Quote: 引用:

没测试代码,看不出什么效果,不过你的是for循环,ie和firefox应该也不可能看到1条加完等待一下在添加另外一条的效果吧,这个执行时间肉眼分辨不出来吧。

要是你要哪种效果,可以用setTimeout延时来执行,不用for语句


    var i = 0;

function addDiv() {
var bone, btwo, bthree, shotCol;
bone = document.getElementById("cols1").offsetHeight;
btwo = document.getElementById("cols2").offsetHeight;
bthree = document.getElementById("cols3").offsetHeight;
var div = document.createElement("div");
div.className = "img_box";
div.innerHTML = '<img src="images/' + Math.ceil(Math.random() * 7) + '.jpg" width="300px" />';
if (bone - btwo <= 0 && bone - bthree <= 0) {
shotCol = "cols1";
}
else if (btwo - bone <= 0 && btwo - bthree <= 0) {
shotCol = "cols2";
}
else {
shotCol = "cols3";
}
document.getElementById(shotCol).appendChild(div);
i++;
if (i < 2) setTimeout(addDiv, 500);////////
}
setTimeout(addDiv, 500);


如果LZ的意思是lazyload方式进行添加的话,那在#2中showbo已经给出了办法呀


哇咔咔,没错,就是#2的办法解决了问题,用setTimeout来延迟执行,这样chrome就会正确加载了。这里我结贴之前总结一下:
1.for循环的时候,IE,和FF是实时更新了页面,所以能够正确算出各个列的offsetHeight;
2.chrome下,我猜测是 代码虽然改变了,但是页面没有被更新…一直到代码有一个较大时间的停顿的时候才会更新页面,所以会导致offsetHeight计算不正确;其实也可能是代码已经进去了…但是图片还没加载…所以拿到高度还是原来的高度…因为没加载图片,所以高度撑不起来…
3.所以解决办法就是用通用的延迟执行(延迟递归调用),这个时候不管是IE,FF 还是chrome都正确计算出了offsetHeight,也就能正确加载瀑布流了。给出我修复后的代码如下(只是替代for循环的那部分哈):
//添加子元素
var myTimeOutI=0;
function addElement()
{
var bone,btwo,bthree,shotCol;
bone = document.getElementById("cols1").offsetHeight;
btwo = document.getElementById("cols2").offsetHeight;
bthree = document.getElementById("cols3").offsetHeight;
var div = document.createElement("div");
div.className = "img_box";
div.innerHTML = '<img src="images/'+Math.ceil(Math.random()*7)+'.jpg" width="300px" />';
if(bone - btwo <= 0 && bone - bthree <= 0)
{
shotCol = "cols1";
}
else if(btwo - bone <= 0 && btwo - bthree <= 0)
{
shotCol = "cols2";
}
else if(bthree - bone <= 0 && bthree - btwo <= 0)
{
shotCol = "cols3";
}
document.getElementById(shotCol).appendChild(div);
myTimeOutI++;
if(myTimeOutI<10)
{
setTimeout(addElement,50);
}
if(myTimeOutI>=10)
{
window.onscroll = showPinterest;
}
}
addElement();

之前本人提供的方法的确是错误的,是因为后面测试时候加载图片没加上Math.random清除缓存。

研究下后纠正下LZ的总结:
chrome没效果是因为for循环太快,你图片没加载完时候你的循环就可能已经结束了,所以肯定获取不到正确的高度。
但在ie下面你在把img加入dom后浏览器根据你的width自动默认先给你分配一个height(比如width=300时,分配height=321,width=600则height=643),所以你下次循环能取到一个height。fiefox没测,估计也是这样的。

根据这个结论2#的方法延迟500ms也并不能保证正确,因为图片加载时间很可能超过500ms,LZ你可以在chrome实验下图片加载时间比较长的情况。


------解决方案--------------------


看来,图片应该预先加载,
,进一步看,应该先写个预先加载random函数。
[解决办法]
急chrome对于js的for循环执行有关问题我的意思是,如果是图片类的,你上传图片的时候可以取了它的高度存储起来.至于你说的只能等img的onload之后才能,倒是有不同的方法的 再谈javascript图片预加载技术

读书人网 >JavaScript

热点推荐