“Javascript: void (0);” проти “return false” проти “prevenDefault ()”


75

Коли я хочу, щоб якесь посилання нічого не робило, а лише відповідало на дії javascript, який найкращий спосіб уникнути прокрутки посилання до верхнього краю сторінки?
Я знаю кілька способів зробити це, всі вони, здається, працюють нормально:

<a href="javascript:void(0)">Hello</a>

або

<a id="hello" href="#">Hello</a>
<script type="text/javascript>
  $(document).ready(function() {
    $("#toto").click(function(){
      //...
      return false;
    });
  });
</script>

і навіть :

<a id="hello" href="#">Hello</a>
<script type="text/javascript>
  $(document).ready(function() {
    $("#toto").click(function(event){
      event.preventDefault();          
      //...
    });
  });
</script>

У вас є якісь переваги? чому? в яких умовах?

PS: звичайно, наведені вище приклади припускають, що ви використовуєте jquery, але є еквіваленти для mootools або прототипу.

Відповіді:


68

Зв'язування:

  • javascript: URL-адреси - це жах, якого слід уникати постійно;
  • атрибути вбудованого обробника подій теж не є чудовими, але добре для швидкого розвитку / тестування;
  • прив'язка зі сценарію, залишаючи розмітку чистою, як правило, вважається найкращою практикою. jQuery заохочує це, але немає жодної причини, чому ви не можете цього зробити в жодній бібліотеці чи простому JS.

Відповіді:

  • У jQuery return falseозначає і те, preventDefaultі stopPropagation, отже, значення інше, якщо ви дбаєте про батьківські елементи, які отримують повідомлення про подію;
  • jQuery приховує це тут, але preventDefault/ stopPropagationв IE зазвичай слід писати по-іншому ( returnValue/ cancelBubble).

Однак:

  • У вас є посилання, яке не є посиланням. Це нікуди не посилається; це дія. <a>насправді не є ідеальною націнкою для цього. Це піде не так, якщо хтось спробує натиснути його середнім клацанням, або додати до закладок, або будь-яку іншу ціну, яку має посилання.
  • У випадках, коли він дійсно вказує на щось, наприклад, коли він відкриває / закриває інший елемент на сторінці, встановіть посилання, на яке вказує, #thatelementsidта використовуйте ненав’язливий сценарій, щоб захопити ідентифікатор елемента з імені посилання. Ви також можете пронюхати при location.hashзавантаженні документа, щоб відкрити цей елемент, тому посилання стане корисним в інших контекстах.
  • В іншому випадку для чогось, що є суто дією, було б найкраще позначити це як одне: <input type="button">або <button type="button">. Ви можете стилізувати його за допомогою CSS, щоб виглядати як посилання замість кнопки, якщо хочете.
  • Однак є деякі аспекти стилю кнопок, яких неможливо повністю позбутися в IE та Firefox. Зазвичай це не суттєво, але якщо вам дійсно потрібен абсолютний візуальний контроль, компроміс полягає у використанні <span>замість нього. Ви можете додати tabindexвластивість, щоб зробити його доступним для клавіатури в більшості браузерів, хоча це насправді не є належним чином стандартизованим. Ви також можете виявити натискання клавіш, як пробіл або Enter, щоб активувати його. Це начебто незадовільно, але все ж досить популярно (ТО, наприклад, це подобається).
  • Інша можливість є <input type="image">. Це має переваги доступності кнопки із повним візуальним контролем, але лише для кнопок чистого зображення.

2
+1, але я не згоден з "атрибути вбудованого обробника подій теж не є чудовими". Якщо вам не потрібні кілька обробників, такі атрибути тегів, як onclickна сьогоднішній день, є найпростішим і найчистішим способом приєднання обробника події до елемента.
casablanca

Дякую за повну відповідь. Я ніколи насправді не думаю про це так ... але зараз мені здається зрозумілим, що це не повинно бути посиланням. Я спробую вищезазначені методи введення / інтервалу і подивлюся, що краще підходить. @casablanca Я насправді не згоден, я написав перший приклад, але насправді я його ніколи не використовую. Так само, як я ненавиджу бачити CSS у своєму html, я справді вважаю, що код JavaScript завжди повинен бути ненав’язливим і залишатися для зовнішніх файлів.
Mike

6
Я повністю погоджуюся з "атрибути вбудованого обробника подій теж не є чудовими". Вони можуть бути простими для швидкого створення прототипів, але коли вам потрібно додати цей 2-й обробник, ви швидко стаєте непослідовними в тому, як ви прикріплюєте обробники, і невідповідність призводить до помилок. Посилання має працювати самостійно, як стверджує bobince, а посилення його для виконання вигадливих подвигів повинно бути частиною контролера , який слід тримати окремо від моделі та виду
Стівен П

3
Стівен П. - цілком згоден, за винятком того, що MVC є "правильною справою" :) Це лише один із способів організації речей (загальновідомий популярний), і він має свої сторони, як і все інше.
sje397

1
Якщо вам ніколи не знадобиться більше однієї функції слухача для певної події та елемента і ви знаєте власну думку, то в атрибутах обробника подій немає нічого поганого. Насправді вони мають перевагу над будь-яким іншим методом прив'язки подій, що працює відразу, не дочекавшись, поки інший сценарій завантажиться та зробить прив'язку.
Тім Даун

18

Єдина перевага, яку я можу придумати використовувати, javascript:void(0)полягає в тому, що вона буде підтримуватися навіть найстарішими браузерами. Тим не менш, я скористався одним із інших ненав’язливих підходів, про які ви згадали:

  • Для більшості застосувань, event.preventDefault()і return falseможуть бути використані як взаємозамінні.
  • event.preventDefault()запобіжить перезавантаженню сторінки за бажанням, але дозволить події клацання піднятися до батьківської. Якщо ви хочете зупинити бульбашки, ви можете використовувати його разом з event.stopPropagation.
  • return false додатково зупинить подію, яка надходить до батьків.

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

Розглянемо наступний приклад:

<div>Here is some text <a href="www.google.com">Click!</a></div>​

$("a").click(function(e) {
    e.preventDefault();
});

$("div").click(function() {
    $(this).css("border", "1px solid red");
});
​

Натискання на прив'язку перешкоджатиме спрацьовуванню дії події за замовчуванням, тому браузер не переспрямовуватиме на www.google.com. Однак подія все одно "спливає" і спричиняє активацію події натискання div, що додасть межу навколо неї. Додати e.stopPropagation() або просто, return false і подія натискання div не запускатиметься. Ви можете возитися з цим тут: http://jsfiddle.net/cMKsN/1/


Зацікавленість: чи ефективний виклик event.precentdefault()у верхній частині обробника, якщо після цього у коді обробника виникає виняток?
sje397

@ sje397 Так, якщо у вас є event.preventDefault(); someFunction();і щось зламалося з someFunction (), подія за замовчуванням все одно зупиняється.
Роберт,

Ну, ви бачите підтримку браузера там, але також гарне пояснення обох світів, зупиніть розповсюдження та запобігайте За замовчуванням +1
Лев

2

Dreamweaver використовує приємний маленький трюк за замовчуванням, який я почав використовувати.

<a href='javascript:;'></a>

Це невелике, воно не спрацьовує і не закріплюється, і це агностик бібліотеки.


Думаю, це той самий приклад, що і мій перший. Браузер чекає URL-адреси, і в обох випадках вираз оцінюється як нуль або невизначений (null == undefined).
Mike

@Mike: Це насправді оцінює undefinedв обох випадках. nullє дійсним значенням JavaScript і не є таким, як undefined.
casablanca

@casablanca: все ще вважає, що (null == undefined) === true, (null === undefined) === false.
weiglt

Гарний! Це саме те, що мені потрібно було!
Нік

1

Я, як правило, віддаю перевагу використанню return false, оскільки це дає можливість дати користувачеві вибір, чи продовжувати цю дію, як показано тут, у режимі quirksmode:

http://www.quirksmode.org/js/events_early.html#default

Це просто, це старий, але він працює добре, переглядач, незалежно від версії JavaScript.


1

event.preventDefault()і return false;одне - вони вказують браузеру не обробляти дію за замовчуванням для події (у цьому випадку перехід до href тегу прив'язки, по якому клацнули). href=javascript:і подібні йому щось інше - вони спричиняють типовою дією „нічого не робити“.

Це питання стилю. Ви хочете виконувати всю свою роботу в режимі onclick або хочете мати можливість здійснювати дії як у onclick, так і у href і покладатися на можливості браузера для модуляції між ними?


2
event.preventDefault()і return false;це НЕ одна річ
Тімо Huovinen

1

Мені подобається використовувати href="javascript:void(0)"в посиланні як# передбачає перехід до верхньої частини сторінки, і це насправді може статися, якщо з якихось причин ваша подія jQuery не завантажується, наприклад, jQuery не завантажується.

Я також використовую, event.preventDefault();оскільки він не буде переходити за посиланням, навіть якщо виникне помилка перед поверненням false; наприклад:

HTML:

<a id="link" href="http://www.google.com">Test</a>

Приклад jQuery 1:

$("#link").click(
    function(){
        alert("Hi");
        invalidCode();
        return false;
    }
);

jQuery Приклад 2:

$("#link").click(
    function(event){
        event.preventDefault();
        alert("Hi");
        invalidCode();
        return false;
    }
);

Оскільки invalidCode();помилка "скидання" return falseніколи не досягається, і якщо використовується jQuery Example 1, користувач буде перенаправлений до Google, тоді як у jQuery Example 2 він цього не зробить.


1

Я думаю, що я бачив і javascript :; навколо розвитку Інтернету важко відстежувати прийоми, які доступні там .. але це в основному про доступність (крім javascript: void (0);) і лише невелика виправка не javascript: void (0) але javascript: void (0); що означає нічого не робити настільки, як повертати false; хоча не впевнений, чи javascript: return false; робить те саме ..

Я завжди використовую і пропоную використовувати javascript: void (0); з кількох причин .. на мій скромний погляд, звичайно.

1.) Я використовую його через того самого, кого згадано вище. Href = "#" не підходить, оскільки це може вказувати на перехід вгору, і навіть у такому випадку "#top" буде більш відповідним для цього випадку. Але також це може викликати щось інше у вашому коді, яке використовує # (хеші), тому іншою причиною є уникнення конфліктів з іншим javascript, який може використовувати #. І я схильний шукати це, наприклад, використовуючи плагін, і негайно їх замінювати .. href = '#' на href = 'javascript: void (0);' або href = 'javascript :;'

2.) Якщо я хочу повторно використовувати функцію для групи конкретних тегів Anchor, я можу зателефонувати їй за допомогою селектора за будь-яким атрибутом, не турбуючись про виявлення події клацання та запобігання дії за замовчуванням, і я роблю це, навіть не думаючи про це як перевага розвитку.

3.) У більшості випадків, якщо ви створюєте посилання за допомогою JavaScript: void (0); намагається зробити посилання, якого не слід, оскільки старий href = rel = nofollow, щоб уникнути індексації посилань, які є діями. Я не настільки впевнений у цьому лише тому, що чув, що сканери та роботи тепер можуть читати навіть Flash, тому не здивуюся, якщо вони зможуть прочитати посилання на javascript

4.) Посилаючись на 2.) ви можете націлитись на клас, як і забути про запобігання дії за замовчуванням події кліку, використовуючи href = "javascript: void (0);" а потім націлювання на клас безпосередньо з селектора за допомогою функції jQuery.

        jQuery(function($)
        {
            //from the rel
            $('a[rel="-your-rel-id"]') ... off('click').on('click',function()

            //from the class
            $('a.-the-class') ... off('click').on('click',function()

            //from the id

            $('a#-the-id').off('click').on('click',function()
            {
            --do something with this link
        });

}); 

Мені швидше комфортніше користуватися класом, як це завжди можна зробити ...

$ (a # -your-id) .hasClass (-yourclass-)

або будь-яку іншу цікаву комбінацію, що впливає на багато посилань .. тому я справді не пропоную використовувати A як селектор виключно ..

Зазвичай я бачу, що тут пропонується:

  jQuery(function($)
        {
            //from the rel
            $('a[rel="-your-rel-id"]').on('click',function(event)
            //do something
            //prevent the click as is passed to the function as an event
            event.preventDefault();
        });

});

0

Я волів би не вкладати JavaScript у те, hrefщо це не для чого він призначений. Я віддаю перевагу щось подібне

<a href="#" onclick="return handler();">Link</a>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.