2008-12-04 54 views
5

setTimeout函數似乎總是給我帶來麻煩。現在我有一個遞歸函數(通過setTimeout調用它自己)並更改元素高度。Javascript的setTimeout函數不會調用

函數發送兩個參數:要更改的元素和元素的最大高度。該功能的目的是展開元素,或以不變的速度「向下滑動」。我知道我可以用jQuery解決這個問題,但我正在嘗試自己的功能。

function slide_down(element, max_height) 
{ 
    if(element.clientHeight < max_height) 
    { 
     var factor = 10; 
     var new_height = (element.clientHeight + factor >= max_height) ? max_height : (element.clientHeight + factor); 
     element.style.height = new_height + 'px'; 

     var func_call = 'slide_down(' + element + ', ' + max_height + ');'; 
     window.setTimeout(func_call, 10); 
    } 
} 

我已經測試了函數初始調用時的參數。 max_height被設置爲20,因爲它是元素所需的高度(我從.scrollHeight得到了這個值)。

當函數完成後,我想讓它自己調用,直到max_height是元素的高度。我這樣做setTimeout調用:

var func_call = 'slide_down(' + element + ', ' + max_height + ');'; 
window.setTimeout(func_call, 10); 

而且它不工作。這確實工作:

var func_call = 'alert(1);'; 
window.setTimeout(func_call, 10); 

我也試着把函數直接調用setTimeout語句,仍然不起作用。

請注意,該元素的高度DOES會改變第一次迭代,該函數從未自行調用。所以元素變量設置正確,我用alert()來顯示max_height也是正確的。

​​

資訊:

slide_down([object HTMLParagraphElement], 20); 

回答

19

當你這樣做:

var func_call = 'slide_down(' + element + ', ' + max_height + ');'; 

你轉換元件爲字符串,所以你超時看起來像

slide_down("[Object]", 100); 

這顯然是行不通的。

你應該做的是創建一個閉包 - 它有點複雜,但基本上你創建了一個函數,舊函數中的局部變量在新函數中仍然可用。

function slide_down(element, max_height) 
{ 
    if(element.clientHeight < max_height) 
    { 
     var factor = 10; 
     var new_height = (element.clientHeight + factor >= max_height) ? max_height : (element.clientHeight + factor); 
     element.style.height = new_height + 'px'; 

     var func = function() 
     { 
      slide_down(element, max_height); 
     } 

     window.setTimeout(func, 10); 
    } 
} 

另外10是一個短暫的超時 - 我建議使用50作爲最低限度。

1

我有過類似經歷。當下一次傳遞元素時,它將在函數調用中轉換爲一個字符串,所以當函數運行時,它會嘗試查找名爲[object] .string或其他內容的元素,而不是您想要的內容。

嘗試更改函數參數以獲取元素的id,並執行document.getElementById()函數內的第一件事。

0

兩件事情:

有一個替代方法調用中傳遞的功能和參數,而不是執行字符串setTimeout()。實際上,the Gecko DOM manual states表示不建議您撥打setTimeout()的版本。

相反的:

var func_call = 'slide_down(' + element + ', ' + max_height + ');'; 
window.setTimeout(func_call, 10); 

試試這個:

window.setTimeout(slide_down, 10, element, max_height); 

更新:如RoBorg提到的,這可能無法在IE瀏覽器,所以你不妨忽略它。


2。我有一種感覺,從setTimeout()自己調用的函數中調用setTimeout()要麼不被允許,要麼不能正常工作。我假設你正在鏈接這樣的調用,因爲你想要代碼重複執行?如果是這樣,那就是window.setInterval()

+0

Mozilla DOM手冊是否錯誤...? – 2008-12-04 17:39:42

+0

嗯我想我從來沒有遇到過這種語法,因爲「請注意,在第一種語法中向函數傳遞附加參數在Internet Explorer中不起作用」。你的第一個鏈接在404之前出現了,所以無論你編輯還是這是一個小故障。 -1刪除 – Greg 2008-12-04 17:42:05

3

首先,這個「現在我有一個遞歸函數(通過setTimeout調用自己)」尖叫setInterval給我,如果你不改變時期。

其次,這是因爲元素引用在字符串concat中丟失,因爲element.toString()將是「[object]」。嘗試傳入一個ID,你可以重新找到,存儲一個參考水平,或者(正如我剛剛看到馬特B指出)擴大的方法形式。

1

您的代碼存在的問題是您無法傳遞元素參數。

相反的:

 
var func_call = 'slide_down(' + element + ', ' + max_height + ');'; 

window.setTimeout(func_call, 10); 

嘗試使用匿名函數:

 

window.setTimeout(function() { 
    slide_down(element, max_height) 
}, 10); 

@ matt.b:突入setTimeout調用(你的方式),參數不支持IE。

2

寫作方法(如擴展Gregs答案)的更微妙的方式:

function slide_down(element, max_height) 
{ 
    if(element.clientHeight < max_height) 
    { return; } 

    var factor = 10, 
     new_height = element.clientHeight + factor, 
     f = arguments.callee; 

    if(new_height > max_height) 
    { new_height = max_height; } 

    element.style.height = new_height + 'px'; 

    window.setTimeout(function() { f(element, max_height); }, 10); 
} 

此示例代碼的真正優勢是利用arguments.callee。這樣你就不會打破你的功能,如果你決定重新命名它。我還簡化了new_height賦值。舊代碼中的問題是你執行了element.clientHeight + factor兩次,這有點不明朗。並不是說它在這種情況下對你的表現有任何明顯的影響。但是避免一遍又一遍地計算相同的東西總是好的,但只是將結果存儲起來以備後用。