В чем разница между разными методами помещения кода JavaScript в <a>?

87

Я видел следующие методы помещения кода JavaScript в <a>тег:

function DoSomething() { ... return false; }
  1. <a href="javascript:;" onClick="return DoSomething();">link</a>
  2. <a href="javascript:DoSomething();">link</a>
  3. <a href="javascript:void(0);" onClick="return DoSomething();">link</a>
  4. <a href="#" onClick="return DoSomething();">link</a>

Я понимаю идею попытки поместить действительный URL-адрес вместо простого кода JavaScript, на всякий случай, если у пользователя не включен JavaScript. Но для целей этого обсуждения я должен предположить, что JavaScript включен (они не могут войти без него).

Мне лично нравится вариант 2, поскольку он позволяет увидеть, что будет запущено - особенно полезно при отладке, когда в функцию передаются параметры. Я использовал его довольно много и не обнаружил проблем с браузером.

Я читал, что люди рекомендуют 4, потому что это дает пользователю реальную ссылку для перехода, но на самом деле # не "настоящий". Это никуда не денется.

Есть ли тот, который не поддерживается или действительно плохой, если вы знаете, что у пользователя включен JavaScript?

Связанный вопрос: Href для ссылок JavaScript: «#» или «javascript: void (0)»? .

Дэррил Хайн
источник
Небольшая синтаксическая проблема: выбор № 2 должен быть - <a href="javascript:DoSomething();"> ссылка </a> без «возврата»
DRosenfeld
Измените принятый ответ на ответ @eyelidlessness. Я думаю, что это лучший подход, потому что он заботится о семантике.
Michał Perłakowski

Ответы:

69

Мне очень нравится статья Мэтта Круза о передовых методах работы с Javascript . В нем он заявляет, что использование hrefраздела для выполнения кода JavaScript - плохая идея. Несмотря на то, что вы заявили, что у ваших пользователей должен быть включен JavaScript, нет причин, по которым у вас не может быть простой HTML-страницы, на которую могут указывать все ваши ссылки JavaScript для своего hrefраздела, в случае, если кто-то отключит JavaScript после входа в систему. Я настоятельно рекомендую вам разрешить этот резервный механизм. Что-то вроде этого будет соответствовать «лучшим практикам» и достигнет вашей цели:

<a href="javascript_required.html" onclick="doSomething(); return false;">go</a>
коровник
источник
4
как значение href будет отображаться пользователю в строке состояния? (полоса внизу) Я бы подумал об использовании более удобной ссылки, например. «js.html? doSomething» страница может быть статическим HTML. Таким образом, пользователь будет четко видеть разницу между ссылками.
Джин,
7
Вы можете переопределить это значение с помощью атрибута title, например <a href="javascript_required.html" title="Does Something" onclick="doSomething(); return false;"> go </a>
Conspicuous Compiler
Лучше всего регистрировать запросы к странице javascript_required.html и регистрировать функцию, вызвавшую ошибку.
Тимо Хуовинен
2
Вы думали о последствиях для SEO?
DanielBlazquez
Сайт javascripttoolbox.com Мэтта Круза, похоже, не работает и продается.
showdev
10

Зачем вам это делать, если вы можете использовать addEventListener/ attachEvent? Если href-эквивалент отсутствует , не используйте <a>, используйте a <button>и задайте соответствующий стиль.

без век
источник
9
использование кнопки вместо ссылки во многих случаях невозможно.
nickf
2
Потому что это выглядит некрасиво. Вы можете добавить значок рядом со ссылкой. Их сложно отформатировать одинаково в разных браузерах. И обычно люди переходят к ссылкам, а не к кнопкам - посмотрите на большую часть переполнения стека.
Дэррил Хайн,
2
Это выглядит некрасиво? Он выглядит так, как вы хотите. На самом деле, я думаю, что кнопки на самом деле имеют большую гибкость стиля, чем ссылки, поскольку они встроены, но могут правильно использовать отступы в браузерах. Что касается CSS, все, что можно сделать со ссылкой, можно сделать с помощью кнопки.
век
2
Диапазон не может быть ориентирован на клавиатуру.
bob с
3
И кнопка семантически верна (ахает). Span семантически бессмысленна. Кнопка - это именно то, что автор намеревается использовать семантически.
век
5

Вы забыли другой метод:

5: <a href="#" id="myLink">Link</a>

С кодом JavaScript:

document.getElementById('myLink').onclick = function() {
    // Do stuff.
};

Я не могу прокомментировать, какой из вариантов имеет лучшую поддержку или какой семантически лучший, но я просто скажу, что мне больше нравится этот стиль, потому что он отделяет ваш контент от вашего кода JavaScript. Он сохраняет весь код JavaScript вместе, что намного проще поддерживать (особенно если вы применяете это ко многим ссылкам), и вы даже можете поместить его во внешний файл, который затем можно упаковать для уменьшения размера файла и кэшировать в клиентских браузерах.

Nickf
источник
7
Если у вас есть 20 или 30 разных ссылок с JS, это может оказаться довольно утомительным и в итоге закончится большим количеством JS.
Дэррил Хайн,
это не более утомительно, чем пробираться через HTML, чтобы изменить javascript. ... или вы можете использовать что-то вроде jQuery, который может легко изменять события сразу на нескольких элементах ... $ ('# menu a'). click (function () {..})
nickf
1
@JKirchartz Я не понимаю, как он проповедует, если за ответом есть причины. Если вы читаете вопрос, это действительно «какой из этих 4 лучший», и я просто указал, что есть еще один вариант, который он не рассматривал.
nickf
Плевать, трололо, выбирая между ABC и D, нельзя выбирать E.
JKirchartz
3
@JKirchartz Да, я не думаю, что тогда вы действительно понимаете цель Stack Overflow. Если кто-то спросит: «На чем лучше создавать веб-приложение: на Cobol или Fortran?» Приемлемо сказать этому человеку, что он не рассмотрел все возможности. Вопрос явно не в том, «какая из этих четырех вещей самая лучшая».
nickf
3
<a href="#" onClick="DoSomething(); return false;">link</a>

Я сделаю это, или:

<a href="#" id = "Link">link</a>
(document.getElementById("Link")).onclick = function() {
    DoSomething();
    return false;
};

В зависимости от ситуации. Для более крупных приложений лучше всего подходит второй, потому что он объединяет ваш код события.

Аник Ислам Абхи
источник
Если у вас есть 20 или 30 разных ссылок с JS, это может оказаться довольно утомительным и в итоге закончится большим количеством JS.
Дэррил Хайн,
а ошибки, которые вкрадываются в ваш код, может быть ОЧЕНЬ сложно отладить. Эти ошибки появляются очень легко, о чем свидетельствует ваш первый пример. :)
nickf
1

Метод № 2 имеет синтаксическую ошибку в FF3 и IE7. Я предпочитаю методы №1 и №3, потому что №4 загрязняет URI символом «#», хотя и вызывает меньше ввода ... Очевидно, как отмечается в других ответах, лучшим решением является отделение HTML от обработки событий.

Пьер Луиджи
источник
Метод №2 чего? Вопросы не стоят в том же порядке, как когда ВЫ их видели.
Диодеус - Джеймс Макфарлейн,
Метод №4 не испортит URI, если вы обязательно это сделаете return false. По этой причине метод №4, вероятно, лучший (из перечисленных).
Már Örlygsson,
2
@Diodeus, я полагаю, что Пьер имел в виду нумерованный список в вопросе , который на самом деле был там с момента публикации вопроса.
Без век
1

Я заметил одно различие между этим:

<a class="actor" href="javascript:act1()">Click me</a>

и это:

<a class="actor" onclick="act1();">Click me</a>

это если в любом случае у вас есть:

<script>$('.actor').click(act2);</script>

то для первого примера act2будет выполняться раньше, act1а во втором примере будет наоборот.

JoelFan
источник
1

Только современные браузеры

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
(function(doc){
    var hasClass = function(el,className) {
        return (' ' + el.className + ' ').indexOf(' ' + className + ' ') > -1;
    }
    doc.addEventListener('click', function(e){
      if(hasClass(e.target, 'click-me')){
          e.preventDefault();
          doSomething.call(e.target, e);
      }
    });
})(document);

function doSomething(event){
  console.log(this); // this will be the clicked element
}
</script>
<!--... other head stuff ...-->
</head>
<body>

<!--buttons can be used outside of forms https://stackoverflow.com/a/14461672/175071 -->
<button class="click-me">Button 1</button>
<input class="click-me" type="button" value="Button 2">

</body>
</html>

Кроссбраузерность

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
(function(doc){
    var cb_addEventListener = function(obj, evt, fnc) {
        // W3C model
        if (obj.addEventListener) {
            obj.addEventListener(evt, fnc, false);
            return true;
        } 
        // Microsoft model
        else if (obj.attachEvent) {
            return obj.attachEvent('on' + evt, fnc);
        }
        // Browser don't support W3C or MSFT model, go on with traditional
        else {
            evt = 'on'+evt;
            if(typeof obj[evt] === 'function'){
                // Object already has a function on traditional
                // Let's wrap it with our own function inside another function
                fnc = (function(f1,f2){
                    return function(){
                        f1.apply(this,arguments);
                        f2.apply(this,arguments);
                    }
                })(obj[evt], fnc);
            }
            obj[evt] = fnc;
            return true;
        }
        return false;
    };
    var hasClass = function(el,className) {
        return (' ' + el.className + ' ').indexOf(' ' + className + ' ') > -1;
    }

    cb_addEventListener(doc, 'click', function(e){
      if(hasClass(e.target, 'click-me')){
          e.preventDefault ? e.preventDefault() : e.returnValue = false;
          doSomething.call(e.target, e);
      }
    });
})(document);

function doSomething(event){
  console.log(this); // this will be the clicked element
}
</script>
<!--... other head stuff ...-->
</head>
<body>

<!--buttons can be used outside of forms https://stackoverflow.com/a/14461672/175071 -->
<button class="click-me">Button 1</button>
<input class="click-me" type="button" value="Button 2">

</body>
</html>

Вы можете запустить это до того, как документ будет готов, нажатие кнопок будет работать, потому что мы прикрепляем событие к документу.

Источники:

Тимо Хуовинен
источник