2008-12-04 42 views
5

Hàm setTimeout dường như luôn gây rắc rối cho tôi. Ngay bây giờ tôi có một hàm đệ quy (gọi chính nó thông qua setTimeout) và thay đổi chiều cao của các phần tử.Chức năng setTimeout của Javascript không gọi

Hàm được gửi hai đối số: phần tử được thay đổi và chiều cao tối đa của các phần tử đó. Mục đích của hàm là để mở ra phần tử hoặc "trượt xuống" ở tốc độ không đổi. Tôi biết tôi có thể giải quyết vấn đề này với jQuery, nhưng tôi đang thử chức năng của riêng mình.

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); 
    } 
} 

Tôi đã thử nghiệm các đối số khi hàm được gọi ban đầu. max_height được đặt thành 20 vì nó là chiều cao mong muốn của các phần tử (tôi nhận giá trị này từ .scrollHeight).

Khi chức năng được thực hiện, tôi muốn nó tự gọi cho đến khi max_height là chiều cao của phần tử. Tôi làm điều đó với cuộc gọi setTimeout này:

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

Và nó không hoạt động. THIS này hoạt động:

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

Tôi cũng đã thử thực hiện cuộc gọi hàm trực tiếp vào câu lệnh setTimeout, vẫn không hoạt động.

Lưu ý rằng chiều cao của phần tử KHÔNG thay đổi lần lặp đầu tiên, hàm này không bao giờ tự gọi chính nó. Vì vậy, biến phần tử được đặt chính xác và tôi đã sử dụng alert() để hiển thị max_height cũng chính xác.

alert(func_call); 

Cảnh báo này:

slide_down([object HTMLParagraphElement], 20); 

Trả lời

19

Khi bạn làm điều này:

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

bạn đang chuyển đổi yếu tố để một chuỗi, do đó thời gian chờ của bạn sẽ trông giống như

slide_down("[Object]", 100); 

mà rõ ràng là sẽ không làm việc.

Điều bạn nên làm là tạo ra một đóng cửa - nó phức tạp một chút nhưng về cơ bản bạn tạo một hàm và biến cục bộ từ hàm cũ vẫn có sẵn trong hàm mới.

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); 
    } 
} 

Ngoài ra 10 hơi ngắn để hết thời gian chờ - tôi khuyên bạn nên sử dụng 50 ở mức tối thiểu.

+0

Cảm ơn. Tôi đang tìm kiếm nó. – HOT

1

Tôi đã có một kinh nghiệm tương tự. Khi bạn chuyển phần tử vào lần sau, nó sẽ được chuyển thành một chuỗi trong lời gọi hàm, vì vậy khi hàm chạy, nó cố gắng tìm một phần tử có tên [object] .string hoặc một cái gì đó, thay vì những gì bạn dự định.

Hãy thử thay đổi tham số hàm của bạn để lấy id của phần tử và thực hiện lệnh gọi hàm document.getElementById() đầu tiên bên trong hàm.

0

Hai điều:

1. Có một cách khác để gọi setTimeout() mà bạn vượt qua các chức năng và các thông số, chứ không phải là một chuỗi để thực thi. Trong thực tế, the Gecko DOM manual states rằng phiên bản của bạn gọi setTimeout() không được khuyến nghị.

Thay vì:

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

Hãy thử điều này thay vì:

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

Cập nhật: như RoBorg đề cập, điều này có thể không làm việc trong IE, vì vậy bạn cũng có thể bỏ qua nó.


2. Tôi có cảm giác rằng việc gọi số setTimeout() từ bên trong một hàm được gọi là setTimeout() hoặc là không được phép hoặc không hoạt động tốt. Tôi giả sử rằng bạn đang chuỗi các cuộc gọi như thế này bởi vì bạn muốn mã để thực thi nhiều lần? Nếu vậy, đó là những gì window.setInterval() là dành cho.

+0

Tài liệu hướng dẫn sử dụng Mozilla DOM có sai không ...? –

+0

Hmm Tôi đoán tôi không bao giờ bắt gặp cú pháp đó vì "Lưu ý rằng việc chuyển các tham số bổ sung vào hàm trong cú pháp đầu tiên không hoạt động trong Internet Explorer". Liên kết đầu tiên của bạn đã xuất hiện 404 trước khi bạn chỉnh sửa hoặc đó là sự cố. -1 đã xóa – Greg

+0

Tôi đã khắc phục sự cố với các liên kết, https không được định dạng đúng. cảm ơn. –

3

Trước hết, điều này "Ngay bây giờ tôi có một chức năng đệ quy (gọi chính nó thông qua setTimeout)" hét lên setInterval với tôi nếu bạn không thay đổi khoảng thời gian.

Thứ hai, điều này là do tham chiếu phần tử bị mất trong chuỗi ký tự dưới dạng element.toString() sẽ là "[đối tượng]". Hãy thử đi qua trong một id bạn có thể tìm lại, lưu trữ một tài liệu tham khảo một cấp lên, hoặc (như tôi vừa thấy matt b chỉ ra) các hình thức phương pháp mở rộng.

1

Sự cố với mã của bạn là bạn không thể chuyển tham số phần tử.

Thay vì:

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

window.setTimeout(func_call, 10); 

thử sử dụng chức năng ẩn danh:

 

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

@ matt.b: đối số truyền vào cuộc gọi setTimeout (theo cách bạn làm) không được hỗ trợ trong IE.

2

Một cách tinh tế hơn của văn bản cho phương pháp (như mở rộng Gregs câu trả lời):

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); 
} 

Ưu điểm thực sự của mẫu mã này là việc sử dụng arguments.callee. Bằng cách này bạn sẽ không phá vỡ chức năng của bạn, bạn nên quyết định đổi tên nó. Tôi cũng đã đơn giản hóa việc gán giá trị new_height. Vấn đề trong đoạn mã cũ là bạn đã thực hiện element.clientHeight + factor hai lần, điều này là không đơn thuần. Không phải là nó có bất kỳ hiệu ứng đáng chú ý về hiệu suất của bạn trong trường hợp này. Nhưng nó luôn luôn tốt để tránh tính toán những điều tương tự hơn và hơn, nhưng chỉ lưu trữ kết quả để sử dụng sau này.

Các vấn đề liên quan