Різниця між функціями jQuery `click`,` bind`, `live`,` delegate`, `trigger` та` on` (з прикладом)?


139

Я прочитав документацію кожної функції jQuery official website, але немає таких порівняльних списків між наведеними нижче функціями:

$().click(fn)
$().bind('click',fn)
$().live('click',fn)
$().delegate(selector, 'click', fn)
$().trigger('click') // UPDATED
$().on('click', selector ,fn); // more UPDATED

Будь ласка, уникайте будь-яких посилань.

Як усі вищезгадані функції точно працюють і яким слід віддати перевагу в якій ситуації?

Примітка. Якщо є якісь інші функції, які мають таку ж функціональність або механізм, тоді уточнюйте їх.

Оновлення

Я також бачив $.triggerфункцію. Чи працює він аналогічно вищевказаним функціям?

Більше оновлення

Тепер .onдодано v1.7, і я думаю, що цей спосіб якось покриває всі вищезгадані вимоги до функцій.


3
@ Я, як і PHP, іноді люди виголошують справи, якщо вони не відчувають, що це питання, на яке не можна відповісти в посібнику або здається, що це питання домашнього завдання. не хвилюйтесь, інші люди проголосують за нього, якщо вони вважають його корисним.
typeoneerror

@ Typeoneerror - Дякую за підтримку, я вже читав посібник, і коли я не зрозумів явної різниці, то я публікую тут.
diEcho

3
@I Like PHP - Відредагував питання про трохи очищення ... це часто задають, але рідко таким чином, він може легко бути цінним ресурсом, здатним google. Я згоден з вікі-Робочі запис чого - то , як це було б дуже корисно, я бачу плутанини навколо цього, особливо з .live()і .delegate()майже кожен день, +1 для абсолютно правильне питання.
Нік Крейвер

@Nick Craver Дякую за редагування, насправді я поганий англійською мовою (LOL). Чи є якісь маунальні / посилання на те, як ми можемо розмістити запитання SO. От це просто прийшов досвід
diEcho

@I Like PHP - це трохи обох, тут є чудовий всебічний FAQ для ТА: ТА meta.stackexchange.com/questions/7931 Щодо фразування / коментарів, ви просто починаєте дізнаватися, що підходить і найкращий спосіб передайте свої думки, код> будь-який опис іноді, використовуючи правильне ключове слово, позначаючи належним чином те саме, чим довше ви тут, гадаю, я бачу, що з часом багато плакатів покращуються. Що стосується вашої редагування, .trigger()просто посилайтесь на обробник подій ... Я додам опис до своєї відповіді нижче.
Нік Крейвер

Відповіді:


162

Перш ніж прочитати це, перетягніть цей список подій на іншу сторінку, сам API дуже корисний, і все, що я обговорюю нижче, пов’язане безпосередньо з цієї сторінки .

По-перше, .click(function)це буквально ярлик .bind('click', function), вони рівноцінні. Використовуйте їх, прив'язуючи обробник безпосередньо до елемента , наприклад:

$(document).click(function() {
  alert("You clicked somewhere in the page, it bubbled to document");
});

Якщо цей елемент замінить або викине, цього обробника більше не буде. Також елементи, яких не було під час запуску цього коду для приєднання обробника (наприклад, селектор його знайшов тоді), не отримають обробник.

.live() і .delegate() подібні між собою, .delegate()насправді використовує .live()внутрішньо, вони обидва слухають, коли події перекидаються. Це працює для нових і старих елементів , вони кидають події однаково. Ви використовуєте їх, коли ваші елементи можуть змінюватися, наприклад, додаючи нові рядки, елементи списку тощо. Якщо у вас немає батьківського / загального предка, який залишиться на сторінці і не замінюється в будь-який момент, використовуйте .live()так:

$(".clickAlert").live('click', function() {
  alert("A click happened");
});

Якщо ж у вас десь є батьківський елемент, який не замінюється (тому його обробники подій не збираються побачити), вам слід попрацювати з ним .delegate(), як це:

$("#commonParent").delegate('.clickAlert', 'click', function() {
  alert("A click happened, it was captured at #commonParent and this alert ran");
});

Це працює майже так само, як .live() , , але подія бульбашки менше разів, перш ніж бути захопленими та обробниками виконаними. Ще одне поширене використання обох із них - скажімо, що ваш клас змінюється на елементі, який більше не відповідає селектору, який ви використовували спочатку ... за допомогою цих методів селектор оцінюється в момент події , якщо він відповідає, обробник працює .. .так що елемент більше не відповідає селектору, він більше не буде виконуватись. З .click()проте, обробник подій пов'язаний , прямо на елемент DOM, той факт , що він не відповідає будь-селектор був використаний , щоб знайти його не має ніякого відношення ... ця подія неминуче , і це перебування , поки не зникне цей елемент, або обробник видаляється через .unbind().

Ще одне поширене використання .live()і .delegate()є продуктивність . Якщо ви маєте справу з безліччю елементів, приєднання обробника кліків безпосередньо до кожного елемента є дорогим і трудомістким. У цих випадках економніше налаштувати єдиний обробник і дозволити бульбашці виконувати роботу, погляньте на це питання, де це зробило величезну зміну , це хороший приклад програми.


Запуск - для оновленого питання

Доступні дві основні функції запускання обробника подій, вони підпадають під ту ж категорію "Додаток обробника подій" в API , це .trigger()і.triggerHandler() . .trigger('eventName')має вбудовані ярлики для загальних подій, наприклад:

$().click(fn); //binds an event handler to the click event
$().click();   //fires all click event handlers for this element, in order bound

Тут ви можете переглянути список, включаючи ці ярлики .

Що стосується різниці, .trigger() запускає обробник подій (але не дію за замовчуванням більшу частину часу, наприклад, клацнувши курсор у потрібному місці, натиснувши клацанням <textarea>). Це призводить до того, що обробники подій відбуваються в тому порядку, до якого вони були зв'язані (як це було б у рідній події), спрацьовують з нативними діями події та розгортаються DOM.

.triggerHandler()зазвичай для іншої мети, тут ви просто намагаєтеся запустити пов'язаний обробник (ів), це не спричиняє натиск нативного події, наприклад, подача форми. Він не міхур DOM, і це неможливо (він повертає те, що повертається останній обробник подій для цієї події). Наприклад, якщо ви хотіли викликати focusподію, але насправді не фокусували об'єкт, ви просто хочете код, з яким ви пов'язані.focus(fn) запустив, це зробить це, тоді як .trigger()це зробить так само, як і фактично сфокусував би елемент і міхур.

Ось приклад реального світу:

$("form").submit(); //actually calling `.trigger('submit');`

Це запустить будь-які оброблювачі подання, наприклад плагін перевірки jQuery , а потім спробуйте надіслати <form>. Однак якщо ви просто хотіли перевірити, оскільки він підключений через submitобробник подій, але не надсилати <form>після цього, ви можете використовувати .triggerHandler('submit'), як це:

$("form").triggerHandler('submit');

Плагін заважає обробнику подавати форму шляхом бомбардування, якщо перевірка перевірки не проходить, але за допомогою цього методу нам все одно, що це робить. Незалежно від того, перервали це чи ні, ми не намагаємося подати форму, ми просто хотіли запустити її повторно підтвердити і нічого більше не робити. ( Відмова: Це зайвий приклад, оскільки .validate()в плагіні є метод, але це гідна ілюстрація наміру)


Дуже ретельно. Одне невелике виправлення: triggerне розпалює рідну подію. Під рідним я маю на увазі подію, змодельовану за допомогою fireEvent(IE) або dispatchEvent(w3c).
Півмісяць Свіжий

@Crescent - Оновлено менш неоднозначно, я мав на увазі, що він запускає нативні дії події , як, наприклад, подання форм, посилання після цього тощо ... сподіваємось, оновлення чіткіше :)
Нік Крейвер

@Nick від того, що я читаю, здається, що ваша live()робота відрізняється від тієї, яку ви мені дали тут: stackoverflow.com/questions/3981762/… Чи "вага" все ще викликає занепокоєння при використанні live()?
Яхель

@yahelc - Так, звичайно ... ця відповідь суворо порівнює варіанти обробників подій та їх конкретне призначення. Вагова вартість порівняно з кількістю початкових прив’язок порівняно з тим, якщо ви додаєте що-небудь динамічно проти початкового селектора, все ще залишаються актуальними. Якщо ви структура сторінки не що великий ви не маєте , що багато подій , то все в порядку ... занепокоєння за вагою прямо пропорційна розміру / глибини вашої структури і кількості подій (з тип, який .live()слухає ваш дзвінок, наприклад click), що створюється, оскільки він працює на селекторах для кожного з них.
Нік Крейвер

1
у jQuery 1.7, функція live () застаріла на користь $ (document) .on ().
Синхро

28

Перші два рівноцінні.

// The following two statements do the same thing:
$("blah").click( function() { alert( "Click!" ); } );
$("blah").bind( "click", function() { alert( "Click!" ); } ); 

Друге, однак, може бути використане для прив’язки до декількох подій одночасно, вказавши кілька розділених пробілом імен подій:

$("blah").bind( "click mouseover mouseout", function() { alert( "Click! Or maybe mouse moved." ); } ); 

.liveМетод є більш цікавим. Розглянемо наступний приклад:

<a class="myLink">A link!</a>
<a id="another">Another link!</a>

<script>
    $("a.myLink").click( function() { alert( 'Click!' ); } );

    $("a#another").addClass( "myLink" );
</script>

Після виконання другого рядка сценарію, другий посилання також матиме клас CSS "myLink". Але він не матиме обробника подій, оскільки у нього не було класу, коли подія була прикріплена.

Тепер подумайте, що ви хотіли, щоб це було навпаки: кожного разу, коли посилання з класом "myLink" з'являється десь на сторінці, ви хочете, щоб він мав той самий обробник подій автоматично. Це дуже часто, коли у вас є якісь списки або таблиці, де ви додаєте рядки або комірки динамічно, але хочете, щоб вони поводилися однаково. Замість того, щоб щоразу переносити всі болі при призначенні обробників подій, ви можете використовувати .liveметод:

<a class="myLink">A link!</a>
<a id="another">Another link!</a>

<script>
    $("a.myLink").live( "click", function() { alert( 'Click!' ); } );

    $("a#another").addClass( "myLink" );
</script>

У цьому прикладі друге посилання також отримає обробник подій, як тільки він отримає клас "myLink". Магія! :-)

Звичайно, це не так буквально. Що .liveдійсно робить прикріпити обробник не найбільш зазначеного елемента, але до самого кореня HTML дерева (елемент «тіло»). Події в DHTML мають цю кумедну особливість "пузири". Врахуйте це:

<div> <a> <b>text</b> </a> </div>

Якщо натиснути на "текст", то спочатку елемент <b> отримає подію "клацання". Після цього елемент <a> отримає подію "клацання". А після цього елемент <div> отримає подію "клацання". І так далі - аж до елемента <body>. І ось тут jQuery зловить подію і побачить, чи є якісь "живі" обробники, які стосуються елемента, який спричинив подію, в першу чергу. Акуратно!

І нарешті, .delegateметод. Він просто забирає всіх дітей вашого елемента, які відповідають даному селектору, і додає до них "живий" обробник. Поглянь:

$("table").delegate( "td", "click", function() { alert( "Click!" ); } );

// Is equivalent to:
$("table").each( function() {
    $(this).find( "td" ).live( "click", function() { alert( "Click!" ); } );
} );

Питання?


Щоб бути точним, .live()посилається на documentне <body>:) Ви можете переглянути тут демонстрацію, просто підтягніть консоль, щоб перевірити: jsfiddle.net/aJy2B
Nick Craver

3
Це було зручніше пояснити це таким чином. :-)
Федір Сойкін

4
Досить справедливо в частині "body", але "весь шлях до елемента <body>" невірний, події продовжують кипіти повз там, і це не там, де .live()живуть обробники, це вище, на document:) Ви можете побачити демонстрація цього тут: jsfiddle.net/S2VBX
Нік Крейвер

8

Станом на jQuery 1.7 метод .live () був застарілим. Якщо ви використовуєте версію jQuery <1.7, ніж офіційно рекомендується використовувати .delegate () over .live ().

.live () тепер замінено на .on ().

Найкраще перейти безпосередньо на сайт jQuery для отримання додаткової інформації, але ось поточні версії методу .on ():

.on( events [, selector] [, data], handler(eventObject) )
.on( events-map [, selector] [, data] )

http://api.jquery.com/on/


2

$().click(fn)і $().bind('click', fn)однакові на перший погляд, але $.bindверсія є більш потужною з двох причин:

  1. $().bind()дозволяє призначити один обробник для кількох подій, наприклад, $().bind('click keyup', fn).
  2. $().bind()підтримує події в просторі імен - потужна функція, якщо ви хочете видалити (відв’язати) лише певні обробники подій, до яких зобов’язаний елемент - читайте докладніше у подіях, розміщених у імені .

Live vs delegate: на це вже відповіли в інших відповідях.


1

Тут може допомогти читання API. Однак я знаю, що не вдається, так що ви можете продовжувати лінуватися (так!).

$('#something').click(fn);
$('#something').bind('click',fn);

Тут немає різниці (що я знаю). .clickце просто зручність / допоміжний метод.bind('click'

// even after this is called, all <a>s in
// <div class="dynamic_els"> will continue
// to be assigned these event handlers

$('div.dynamic_els a').live(‘click’,fn);

Це дуже відрізняється, оскільки .liveдодає події до селектора, який ви переходите (якого ви тут не були) і продовжує розглядати DOM, як вузли вставляються / видаляються

$('#some_element').delegate('td','click',fn);

Це відрізняється лише тим, як ви призначаєте обробників подій. .delegateзосереджено на бульбашці подій DOM Основний принцип полягає в тому, що кожна подія просувається вгору через дерево DOM, поки не досягне кореневого елемента ( documentабо windowабо, <html>або <body>я не можу точно згадати).

У будь-якому випадку, ви прив'язуєте onclickобробник до всіх <td>s в межах $('#some_element')(ви повинні вказати селектор, хоча ви могли б сказати $(document)). Коли один із його дітей натискається, подія піднімається до<td> . Потім можна витягти вихідний елемент події (що jQuery робить для вас автоматично).

Це корисно, коли є тонни елементів, і у вас є лише кілька (або одна центральна) точка, через яку ці події будуть проходити. Це економить зусилля браузера та пам'ять для об'єднання цих обробників подій у менше об'єктів.


1
.live() також відпрацьовує висхідну ланцюжок події, насправді .delegate()є обгорткою .live(), це просто додати контекст і прив'язку до елементу іншому , ніж documentзахопити бульбашки. Я думаю, що ваше розуміння того, як працюють барботинг-обробники, трохи не вдається (я думаю, що це найчастіше неправильно зрозумілий аспект jQuery 1.4). Обробник знаходиться лише на елементі, до якого ви його зв'язали, тому будь-який елемент, до якого ви закликали .delegate(), або documentу випадку .live(), коли подія туди перекидається, він перевіряє ціль, щоб побачити, чи відповідає він селектору, і чи виконується так.
Нік Крейвер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.