2015-05-20 12 views
10

Nói rằng tôi có xử lý sự kiện javascript sau:Nếu tôi thực hiện thay đổi DOM trong trình xử lý sự kiện Javascript, các thay đổi có được tăng lên một lần hay chỉ một lần ở cuối?

function handleEvent(e){ 
    document.body.style.backgroundColor = 'green'; 
    longRunningFunction(); 
    document.body.style.backgroundColor = 'red'; 
} 

sẽ trình duyệt đầu tiên hiển thị một nền màu xanh lá cây và sau đó chuyển nó thành màu đỏ? Hoặc hiển thị nền màu đỏ trực tiếp?

Theo thử nghiệm của tôi, màn hình sẽ hiển thị màu đỏ trực tiếp ở cuối trình xử lý sự kiện. Nhưng đó có phải là một phần của đặc điểm kỹ thuật hay chỉ ngẫu nhiên với cách các trình duyệt được triển khai như thế nào?

UPDATE:

Tôi nên làm rõ rằng tôi không phải là "mục tiêu" cho hiệu ứng này. Thay vào đó, tôi muốn có một số bảo đảm rằng điều đó xảy ra không phải. Một số xử lý sự kiện của tôi thay đổi nhiều thứ, và nó làm cho cuộc sống của tôi dễ dàng hơn nếu tôi có thể giả định rằng không có trạng thái trung gian nào được trả về.

+0

tôi nghĩ rằng có một số kiểu sẽ hiển thị ngay lập tức, nếu chúng ảnh hưởng đến bố cục. nói chung, công cụ dom được đằng sau trong một chủ đề mà không stuff.a ngắn thời gian chờ xung quanh hai dòng cuối cùng sẽ đảm bảo màu xanh lá cây cho thấy đầu tiên. – dandavis

+2

Javascript là đơn luồng nên 'longRunningFunction()' của bạn sẽ chặn. Có hay không một vẽ lại có thể xảy ra trong khi bạn đang chạy, tôi chắc chắn sẽ không dựa vào nó. –

Trả lời

11

Đây là những gì sẽ xảy ra trong môi trường thực thi JavaScript:

  1. document.body.style.backgroundColor sẽ thay đổi giá trị của nó để 'green'.
  2. Quy trình chạy dài sẽ chạy.
  3. document.body.style.backgroundColor sẽ thay đổi giá trị thành 'red'.

Không xác định cách thay đổi trong thuộc tính backgroundColor sẽ ảnh hưởng đến giao diện của trang, nếu chuỗi JavaScript bị chặn.

Đây là một ví dụ. Nếu bạn nhấp vào chữ hello, bạn sẽ thấy một chút chậm trễ, và sau đó nền sẽ chuyển sang màu đỏ:

function handleEvent(e){ 
 
    document.body.style.backgroundColor = 'green'; 
 
    longRunningFunction(); 
 
    document.body.style.backgroundColor = 'red'; 
 
} 
 

 
function longRunningFunction() { 
 
    for(var i=0; i<2000000000; ++i) { +i; } 
 
} 
 

 
document.body.addEventListener("click", handleEvent);
<div>hello</div>

Điều này là do công cụ rendering của trình duyệt mà vẽ lại để đáp ứng với những thay đổi CSS các thuộc tính bị chặn bởi hàm JavaScript chặn dài hạn. Đây không phải là hành vi được chỉ định, mà là một thực tế triển khai cho tất cả các trình duyệt. Xem How can I force the browser to redraw while my script is doing some heavy processing? cho một câu hỏi tương tự.

Tôi nghĩ rằng bất kỳ trình duyệt cụ thể nào đều có thể chọn chạy một chuỗi rút lại riêng lẻ đồng thời với chuỗi JavaScript, nhưng tôi không tin bất kỳ trình duyệt chính nào hiện đang làm như vậy. Có thể có sự phức tạp trong điều kiện chủng tộc vốn có trong cách tiếp cận như vậy; Tôi chưa bao giờ viết một trình duyệt nên tôi không biết.


Nếu bạn muốn để hiển thị trạng thái trung gian, bạn có thể sử dụng một setTiemout gọi rất nhanh chóng sau khi cài đặt backgroundColor sang xanh lá cây, để xóa các hàm JavaScript chồng và cho phép các renderer để vẽ lại trang:

function handleEvent(e){ 
    document.body.style.backgroundColor = 'green'; 
    setTimeout(function() { 
     longRunningFunction(); 
     document.body.style.backgroundColor = 'red'; 
    }, 4); 
} 

Hàng đợi này sẽ xếp hàng longRunningFunction và thay đổi màu thứ hai để chạy trong 4 mili giây trong tương lai. Trong thời gian nhàn rỗi đó 4 mili giây, trình kết xuất có cơ hội vẽ lại trang.

+0

Cảm ơn. Tôi đang cố tránh các trạng thái trung gian xuất hiện. Vì nó chủ yếu là một giao diện người dùng (tôi chỉ không muốn người dùng nhìn thấy các nhấp nháy), tôi cảm thấy tốt dựa vào thực tế của các triển khai hiện tại không hiển thị song song với các trình xử lý sự kiện. Không có gì khủng khiếp sẽ xảy ra ngay cả khi nó thay đổi ... – user2771609

0

Điều này có minh họa điều bạn đang nhắm tới không?

function handleEvent(e){ 
    document.body.style.backgroundColor = 'green'; 
    alert(); 
    document.body.style.backgroundColor = 'red'; 
} 
Các vấn đề liên quan