Phương thức jQuery .live () vs .on () để thêm một sự kiện nhấp chuột sau khi tải html động


216

Tôi đang sử dụng jQuery v.1.7.1 trong đó phương thức .live () rõ ràng không dùng nữa.

Vấn đề tôi gặp phải là khi tải động html vào một phần tử bằng cách sử dụng:

$('#parent').load("http://..."); 

Nếu tôi thử và thêm một sự kiện nhấp chuột sau đó thì nó không đăng ký sự kiện bằng một trong các phương pháp sau:

$('#parent').click(function() ...); 

hoặc là

// according to documentation this should be used instead of .live()
$('#child').on('click', function() ...); 

Cách chính xác để đạt được chức năng này là gì? Nó dường như chỉ hoạt động với .live () đối với tôi, nhưng tôi không nên sử dụng phương thức đó. Lưu ý rằng #child là một phần tử được tải động.

Cảm ơn.


25
Tại sao bạn nói "được cho là không dùng nữa" ? Bạn không tin các tài liệu?

6
Nó không cho là chấp nhận: nó được phản đối. Nếu bạn nhìn vào tài liệu jQuery cho.live() nó, nó sẽ cho bạn biết cách viết lại các cách sử dụng hiện có .live()để sử dụng .delegate()hoặc .on()(tùy thuộc vào việc bạn có ở phiên bản 1.7+ hay không). Lưu ý rằng nếu bạn thêm một trình xử lý với .click()"sau đó" như bạn đã đề cập, nghĩa là, sau khi tải các phần tử động, nó sẽ hoạt động - vấn đề duy nhất là cố gắng gán .click() trước khi tải các phần tử động.
nnnnnn

Tôi đã thay đổi từ ngữ thành "rõ ràng" vì đó là những gì tôi muốn nói. Dù sao, tôi hiểu rằng rõ ràng vì sự kiện .load () không đồng bộ nên phần tử #child chỉ có thể được nhận ra một cách đáng tin cậy trong trình xử lý thành công, điều này có ý nghĩa.
Sean Thoman

Câu trả lời:


606

Nếu bạn muốn trình xử lý nhấp hoạt động cho một phần tử được tải động, thì bạn đặt trình xử lý sự kiện trên một đối tượng cha (không được tải động) và cung cấp cho nó một bộ chọn phù hợp với đối tượng động của bạn như thế này:

$('#parent').on("click", "#child", function() {});

Trình xử lý sự kiện sẽ được gắn vào #parentđối tượng và bất cứ khi nào một sự kiện nhấp vào bong bóng bắt nguồn từ #childnó, nó sẽ kích hoạt trình xử lý nhấp chuột của bạn. Điều này được gọi là xử lý sự kiện được ủy nhiệm (việc xử lý sự kiện được ủy quyền cho một đối tượng cha).

Nó được thực hiện theo cách này bởi vì bạn có thể đính kèm sự kiện vào #parentđối tượng ngay cả khi #childđối tượng chưa tồn tại, nhưng khi nó tồn tại và được nhấp vào, sự kiện nhấp sẽ nổi lên #parentđối tượng, nó sẽ thấy rằng nó bắt nguồn từ #childvà có một trình xử lý sự kiện cho một nhấp chuột #childvà kích hoạt sự kiện của bạn.


23
Giải thích tuyệt vời ! Trước đây tôi chưa bao giờ có thể quấn đầu live()so với on()tối nay nhưng tối nay tôi quyết định thử lại lần nữa và lời giải thích của bạn ngay lập tức tiết lộ những gì tôi đã bỏ lỡ suốt thời gian qua. Cảm ơn!
MikeSchinkel

6
Một triệu up . Tôi đã bắt đầu sử dụng loại trực tiếp trước khi tôi nhận ra điều này là có thể trong jQuery cho những đứa trẻ được tạo động, cảm ơn bạn rất nhiều.
Brock Hensley

9
Bạn nên xem xét việc viết một cuốn sách hoặc một cái gì đó: văn bản nhỏ của bạn hữu ích hơn cho tôi so với toàn bộ trang trong các tài liệu jQuery về « on () ». Cảm ơn rất nhiều!
Cholesterol

@ jfriend00 bạn có biết làm thế nào chúng ta có thể áp dụng quy trình tương tự này cho tình huống di chuột, không di chuột không? Có một nguồn nói về điều này?
klewis

@blackhawk - Xem câu trả lời này . Bạn có thể đăng ký mouseentermouseleavecác sự kiện và kiểm tra bên trong trình xử lý đã được kích hoạt. Sự kiện "hover" giả của jQuery không có sẵn với sự ủy nhiệm.
jfriend00

33

Thử cái này:

$('#parent').on('click', '#child', function() {
    // Code
});

Từ $.on()tài liệu:

Trình xử lý sự kiện chỉ bị ràng buộc với các yếu tố hiện được chọn; chúng phải tồn tại trên trang tại thời điểm mã của bạn thực hiện cuộc gọi đến .on().

#childPhần tử của bạn không tồn tại khi bạn gọi $.on()nó, vì vậy sự kiện không bị ràng buộc (không giống như $.live()). #parenttuy nhiên, không tồn tại, vì vậy ràng buộc sự kiện đó là tốt.

Đối số thứ hai trong mã của tôi ở trên hoạt động như một 'bộ lọc' để chỉ kích hoạt nếu sự kiện nổi lên #parenttừ đó #child.


Nếu tôi gọi phương thức $ .on () sau phương thức $ .load (), thì tại sao phần tử #child không tồn tại ở điểm đó?
Sean Thoman

6
@SeanThoman - bạn phải gọi nó từ trình xử lý thành công của .load()phương thức - không phải từ mã sau .load()phương thức. #childchỉ được biết là được tải khi trình xử lý thành công thực sự thực thi chứ không phải trước đó.
jfriend00

và thậm chí sau đó cần có thời gian để chèn bất kỳ dữ liệu nào bạn nhận được vào DOM có nghĩa là nó có thể không kết nối. Gần đây tôi đã làm rất nhiều ứng dụng trang đơn và tiêu chuẩn của tôi là var $ body = $ ('body'); $ body.on ("sự kiện", ".element / # class", hàm (e) {}); cho tất cả. 1 bộ chọn. Không phải lo lắng về những gì được hoặc không được tải.
lupos

21

$(document).on('click', '.selector', function() { /* do stuff */ });

EDIT: Tôi đang cung cấp thêm một chút thông tin về cách thức hoạt động của nó, bởi vì ... từ. Với ví dụ này, bạn đang đặt một người nghe trên toàn bộ tài liệu.

Khi bạn clicktrên bất kỳ (các) yếu tố nào phù hợp .selector, sự kiện sẽ nổi lên trên tài liệu chính - miễn là không có người nghe nào khác gọi event.stopPropagation()phương thức đó - điều này sẽ dẫn đến sự sủi bọt của một sự kiện đối với các phần tử cha.

Thay vì liên kết với một yếu tố cụ thể hoặc tập hợp các yếu tố, bạn đang lắng nghe bất kỳ sự kiện nào đến từ các yếu tố phù hợp với bộ chọn đã chỉ định. Điều này có nghĩa là bạn có thể tạo một người nghe, một lần, sẽ tự động khớp với các phần tử hiện có cũng như bất kỳ phần tử được thêm động nào.

Điều này là thông minh vì một vài lý do, bao gồm cả việc sử dụng hiệu năng và bộ nhớ (trong các ứng dụng quy mô lớn)

BIÊN TẬP:

Rõ ràng, yếu tố cha mẹ gần nhất mà bạn có thể nghe là tốt hơn và bạn có thể sử dụng bất kỳ yếu tố nào thay cho documentnhững đứa trẻ bạn muốn theo dõi các sự kiện nằm trong yếu tố cha mẹ đó ... nhưng điều đó thực sự không có gì để làm với câu hỏi


23
Anh cố gắng $(element).on(...). Đây là $(document).on(...,element,...). Những con thú khác nhau.
cHao

@ArnoldRoa có, hiệu suất tốt hơn. bạn sẽ không có người nghe trên nhiều trẻ em, không phải đăng ký lại người nghe bất cứ khi nào DOM được sửa đổi và các sự kiện sẽ xuất hiện thông qua DOM theo mặc định. Chạy một lần và mọi đứa trẻ khớp với bộ chọn sẽ kích hoạt chức năng đã cho khi nhấp vào.
L422Y

Nhận xét của @ L422Y ở đây rất sai lệch. Nếu bạn tò mò về ý nghĩa hiệu suất, hãy xem nhận xét của @ jfriend00 về câu trả lời của @ Jared
Gust van de Wal

@GustvandeWal Làm thế nào là sai lệch? Nếu bạn đi và phát hành một trăm đô la (này) .on (...) so với việc nghe một sự kiện một lần trên phần tử cha, thì nó thực sự hiệu quả hơn.
L422Y

Bạn chỉ nói về việc gắn các sự kiện. Các nút thắt hiệu suất trong thế giới thực có quá nhiều người nghe bắn ra (như những gì bạn ủy thác), không phải là một lượng lớn các yếu tố cần một sự kiện gắn liền với chúng.
Gust van de Wal

12

Tương đương với .live () trong 1.7 trông như thế này:

$(document).on('click', '#child', function() ...); 

Về cơ bản, hãy xem tài liệu cho các sự kiện nhấp chuột và lọc chúng cho #child.


Bởi vì đó là cách xử lý sự kiện gắn vào tài liệu (cách .live()thực hiện).
cHao

17
Một lý do không .live()được chấp nhận bây giờ là vì thật tệ khi đặt tất cả các trình xử lý sự kiện trực tiếp vào đối tượng tài liệu. Mọi thứ thực sự có thể, thực sự chậm lại. Không chỉ các sự kiện phải tạo bong bóng cho đến tài liệu, mà bạn có thể có rất nhiều trình xử lý sự kiện để xem qua đối tượng tài liệu. Ưu điểm chính của .on()là bạn có thể gắn nó vào một đối tượng cha gần với đối tượng thực tế hơn và cải thiện đáng kể hiệu năng. Vì vậy, ... tôi sẽ KHÔNG khuyên bạn nên sử dụng .on()với đối tượng tài liệu. Tốt hơn nhiều để chọn một đối tượng cha mẹ gần hơn.
jfriend00

Cảm ơn bạn đã làm rõ. Đối với những gì đáng giá thì hiệu suất của các sự kiện đã được cải thiện rất nhiều với on () vì vậy nó sẽ ít gây ra vấn đề hơn trước đây. Nếu gắn với cha mẹ, tôi sẽ cho rằng đó phải là cha mẹ tồn tại trên tài liệu sẵn sàng hoặc bạn sẽ thấy các vấn đề tương tự.
Jared

Tồi tệ nhất, điều này không mô phỏng .live()cách tiếp cận không dùng nữa ; tuy nhiên khả năng kiểm soát đoàn chắc chắn là lợi thế.
Dan Lugg

9

Tôi biết rằng hơi muộn cho một câu trả lời, nhưng tôi đã tạo ra một polyfill cho phương thức .live (). Tôi đã thử nghiệm nó trong jQuery 1.11 và có vẻ như nó hoạt động khá tốt. Tôi biết rằng chúng tôi phải triển khai phương thức .on () bất cứ khi nào có thể, nhưng trong các dự án lớn, nơi không thể chuyển đổi tất cả các lệnh gọi .live () thành các lệnh tương ứng .on () vì bất kỳ lý do gì, có thể sau đây công việc:

if(jQuery && !jQuery.fn.live) {
    jQuery.fn.live = function(evt, func) {
        $('body').on(evt, this.selector, func);
    }
}

Chỉ cần bao gồm nó sau khi bạn tải jQuery và trước khi bạn gọi trực tiếp ().


5

.on () dành cho jQuery phiên bản 1.7 trở lên. Nếu bạn có phiên bản cũ hơn, hãy sử dụng:

$("#SomeId").live("click",function(){
    //do stuff;
});

8
OP nói "Tôi đang sử dụng jQuery v.1.7.1"
Selvakumar Arumugam

1
@ jfriend - tại sao không đăng câu trả lời của riêng bạn thay vì hạ thấp tôi? Tôi sử dụng live () mỗi ngày với tất cả các phiên bản dưới 1.6 và nó hoạt động tốt. Tôi có thể thấy rằng bạn rất giỏi trong việc đọc tài liệu, nhưng đôi khi nó giúp ích nhiều hơn để đưa một cái gì đó vào thực tế cho một người. .live () hoạt động. Giai đoạn = Stage.
Matt Cashatt

5
@MatthewPatrickCashatt - Tôi đã đăng câu trả lời của riêng mình và không đánh giá thấp câu hỏi của bạn - đừng đi những giả định mù quáng như vậy. Pre 1.7, hoạt .delegate()động tốt hơn nhiều so với .live()lý do tại sao tài liệu jQuery khuyến nghị và không dùng nữa .live(). Có, .live()vẫn hoạt động, nhưng câu trả lời ở đây trên SO nên đề xuất cách làm tốt hơn. Tôi đã thấy điều này 20 lần ở đây trên SO. Nếu bạn đăng mã .live()ở đây trên SO, nó sẽ bị hạ cấp (thường không phải do tôi trừ khi có gì đó sai nghiêm trọng với nó).
jfriend00

1
Tôi đã không downvote, nhưng mặc dù .live()chắc chắn hoạt động ngay cả trong phiên bản 1.7, bạn vẫn nên sử dụng .delegate()hoặc .on().live()lý do chính đáng. Miễn là bạn lưu ý thay đổi cú pháp cho hai hàm mới hơn sẽ hoạt động tốt.
nnnnnn

1
@ jfriend00- Bạn hoàn toàn đúng. Ngày dài. Lời xin lỗi của tôi.
Matt Cashatt

3

Tôi đã sử dụng 'live' trong dự án của mình nhưng một người bạn của tôi đã gợi ý rằng tôi nên sử dụng 'on' thay vì live. Và khi tôi cố gắng sử dụng, tôi đã gặp phải một vấn đề như bạn gặp phải.

Trên trang của tôi, tôi tạo các nút bảng hàng và nhiều công cụ dom động. nhưng khi tôi sử dụng phép thuật thì biến mất.

Các giải pháp khác như sử dụng nó như một đứa trẻ chỉ cần gọi các chức năng của bạn mỗi lần nhấp chuột. Nhưng tôi tìm một cách để làm cho nó xảy ra một lần nữa và đây là giải pháp.

Viết mã của bạn dưới dạng:

function caller(){
    $('.ObjectYouWntToCall').on("click", function() {...magic...});
}

Gọi người gọi (); sau khi bạn tạo đối tượng của bạn trong trang như thế này.

$('<dom class="ObjectYouWntToCall">bla... bla...<dom>').appendTo("#whereeveryouwant");
caller();

Bằng cách này, chức năng của bạn được gọi khi nó được cho là không phải mỗi lần nhấp vào trang.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.