2016-04-05 15 views
7

Tôi muốn tạo sự kiện một lần được kích hoạt bằng cách nhấp vào bất kỳ đâu. Sự kiện này được tạo bằng cách nhấp vào nút. Tôi không muốn sự kiện kích hoạt khi nhấp vào nút, chỉ bất kỳ lần nhấp tiếp theo nào ở bất kỳ đâu (bao gồm cả nút).setTimeout và tuyên truyền sự kiện

Vì vậy, nói rằng tôi đã có một số html như sau:

<body> 
    <div id="someparent"> 
    <div id="btn"></div> 
    </div> 
</body> 

Và javascript sau (jquery):

$('#btn').click(function() { 
    $(document).one('click', function() { 
    console.log('triggered'); 
    }); 
}); 

$('#someparent').click(function() { 
    // this must always be triggered 
}); 

Tôi muốn tránh dừng lan truyền sự kiện, nhưng ở trên ví dụ, sự kiện bị ràng buộc vào tài liệu, sự kiện sau đó phát tán và sự kiện được kích hoạt.

Một cách để khắc phục điều này có vẻ là để quấn tạo sự kiện trong một thời gian chờ:

$('#btn').click(function() { 
    setTimeout(function() { 
    $(document).one('click', function() { 
     console.log('triggered'); 
    }); 
    }, 1); 
}); 

$('#someparent').click(function() { 
    // this must always be triggered 
}); 

Bây giờ, làm việc này tốt, nhưng tôi đang tự hỏi liệu điều này là an toàn. Có một số khái niệm về trật tự thực hiện đảm bảo rằng điều này sẽ luôn luôn làm việc, hoặc là nó chỉ làm việc một cách tình cờ? Tôi biết có những giải pháp khác (ví dụ như một sự kiện lồng nhau .one()), nhưng tôi đang tìm kiếm một câu trả lời cụ thể cho cách setTimeout và tuyên truyền sự kiện tương tác.

Fiddle sau hiển thị hai div. Người đầu tiên có hành vi sai (sự kiện tài liệu được kích hoạt ngay lập tức). Nhấp vào div thứ hai, và sau đó bất cứ nơi nào trên tài liệu (vùng trắng) minh họa các hành vi truy nã:

https://jsfiddle.net/Lwocuuf8/7/

+0

bạn không thể dây lên sự kiện nhấn và chỉ cần loại bỏ các xử lý sau khi sự kiện có được kích hoạt (trừ khi nguồn là nút)? –

+0

Tôi không chắc mình hiểu ý của bạn là gì? – jkgeyti

+0

chỉ cần trả về false để ngăn chặn bong bóng – TecHunter

Trả lời

7

bọt tổ chức sự kiện có nghĩa là, sau khi một sự kiện gây nên trên các yếu tố sâu xa nhất có thể, nó sẽ gây nên các bậc cha mẹ trong tổ gọi món.

Từ: https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#Adding_messages

Thêm thông điệp

Trong trình duyệt web, tin nhắn được thêm vào bất cứ lúc nào một sự kiện xảy ra và có là một người biết lắng nghe sự kiện gắn liền với nó. Nếu không có người nghe, sự kiện bị mất. Vì vậy, nhấp chuột vào một yếu tố có trình xử lý sự kiện nhấp chuột sẽ thêm thông báo - tương tự như vậy với bất kỳ sự kiện nào khác.

Gọi setTimeout sẽ thêm thông báo vào hàng đợi sau thời gian được chuyển làm đối số thứ hai. Nếu không có thư nào khác trong hàng đợi, thư được xử lý ngay lập tức; tuy nhiên, nếu có tin nhắn, thông báo setTimeout sẽ phải chờ các tin nhắn khác được xử lý . Vì lý do đó, đối số thứ hai cho biết thời gian tối thiểu là và không phải là thời gian được đảm bảo.

Vì vậy, hành vi mà bạn có, không phải là một cách tình cờ, bạn được đảm bảo rằng các thông điệp trong hàng đợi sẽ được xử lý trước khi xử lý tin nhắn bạn thêm sau một thời gian chờ.

+1

Chính xác những gì tôi đang tìm kiếm. Điều này đảm bảo hành vi mong đợi. Cảm ơn bạn. – jkgeyti

2

Hiểu biết về những gì bạn muốn: sau khi nhấp vào nút "kích hoạt", lần nhấp tiếp theo ở bất kỳ đâu trên trang (bao gồm cả nút "kích hoạt") sẽ kích hoạt sự kiện đặc biệt.Đây có thể dễ dàng xử lý với một lá cờ:

var activationFlag = false; 

$('#btn').click(function(event){ 
    event.preventDefault(); 

    if(!activationFlag) { 
    event.stopPropagation(); 
    console.log('Global event activated'); 
    } 

    activationFlag = true; 
}); 

$('#someparent').click(function(event){ 
    if(activationFlag) { 
    console.log('Time for a special event'); 
    } else { 
    event.preventDefault(); 
    event.stopPropagation(); 
    } 
}); 
+1

Cảm ơn bạn. Đó là một ví dụ giả tạo được xây dựng từ một vấn đề thế giới thực, vì vậy có vẻ hơi lạ. Có nhiều giải pháp tốt hơn so với phương pháp 'setTimeout' mà tôi đã sử dụng, nhưng tôi đã đặc biệt tìm kiếm câu trả lời cho dù hành vi mong đợi đã được đảm bảo hay chưa. Tuy nhiên, tôi đồng ý rằng một lá cờ là giải pháp thích hợp trong trường hợp này, mặc dù tôi sẽ tránh dừng việc truyền sự kiện như bạn làm trong ví dụ của bạn. – jkgeyti

2

Here is a workaround bằng cách sử dụng một lá cờ thay vì một sự kiện thứ hai:

var documentWaitingClick = false; 
$(function() { 
    $(document).on('click', function(e) { 
    if (documentWaitingClick) { 
     //simulate the "one" 
     documentWaitingClick = false; 
     console.log('document click'); 
    } else if (e.target.tagName === 'BUTTON') { 
     documentWaitingClick = true; 
     console.log('button click') 
    } 
    }); 
}); 
Các vấn đề liên quan