Why is using onClick() in HTML a bad practice?

前端 未结 10 2147
我寻月下人不归
我寻月下人不归 2020-11-21 05:07

I have heard many times that using JavaScript events, such as onClick(), in HTML is a bad practice, because it\'s not good for semantics. I would like to know w

相关标签:
10条回答
  • 2020-11-21 05:33

    You're probably talking about unobtrusive Javascript, which would look like this:

    <a href="#" id="someLink">link</a>
    

    with the logic in a central javascript file looking something like this:

    $('#someLink').click(function(){
        popup('/map/', 300, 300, 'map'); 
        return false;
    });
    

    The advantages are

    • behaviour (Javascript) is separated from presentation (HTML)
    • no mixing of languages
    • you're using a javascript framework like jQuery that can handle most cross-browser issues for you
    • You can add behaviour to a lot of HTML elements at once without code duplication
    0 讨论(0)
  • 2020-11-21 05:33

    Revision

    Unobtrusive JavaScript approach was good in the PAST - especially events handler bind in HTML was considered as bad practice (mainly because onclick events run in the global scope and may cause unexpected error what was mention by YiddishNinja)

    However...

    Currently it seems that this approach is a little outdated and needs some update. If someone want to be professional frontend developper and write large and complicated apps then he need to use frameworks like Angular, Vue.js, etc... However that frameworks usually use (or allow to use) HTML-templates where event handlers are bind in html-template code directly and this is very handy, clear and effective - e.g. in angular template usually people write:

    <button (click)="someAction()">Click Me</button> 
    

    In raw js/html the equivalent of this will be

    <button onclick="someAction()">Click Me</button>
    

    The difference is that in raw js onclick event is run in the global scope - but the frameworks provide encapsulation.

    So where is the problem?

    The problem is when novice programmer who always heard that html-onclick is bad and who always use btn.addEventListener("onclick", ... ) wants to use some framework with templates (addEventListener also have drawbacks - if we update DOM in dynamic way using innerHTML= (which is pretty fast) - then we loose events handlers bind in that way). Then he will face something like bad-habits or wrong-approach to framework usage - and he will use framework in very bad way - because he will focus mainly on js-part and no on template-part (and produce unclear and hard to maintain code). To change this habits he will loose a lot of time (and probably he will need some luck and teacher).

    So in my opinion, based on experience with my students, better would be for them if they use html-handlers-bind at the beginning. As I say it is true that handlers are call in global scope but a this stage students usually create small applications which are easy to control. To write bigger applications they choose some frameworks.

    So what to do?

    We can UPDATE the Unobtrusive JavaScript approach and allow bind event handlers (eventually with simple parameters) in html (but only bind handler - not put logic into onclick like in OP quesiton). So in my opinion in raw js/html this should be allowed

    <button onclick="someAction(3)">Click Me</button>
    

    or

    function popup(num,str,event) {
       let re=new RegExp(str);  
       // ... 
       event.preventDefault();
       console.log("link was clicked");
    }
    <a href="https://example.com" onclick="popup(300,'map',event)">link</a>

    But below examples should NOT be allowed

    <button onclick="console.log('xx'); someAction(); return true">Click Me</button>
    
    <a href="#" onclick="popup('/map/', 300, 300, 'map'); return false;">link</a>
    

    The reality changes, our point of view should too

    0 讨论(0)
  • 2020-11-21 05:33

    Your question will trigger discussion I suppose. The general idea is that it's good to separate behavior and structure. Furthermore, afaik, an inline click handler has to be evalled to 'become' a real javascript function. And it's pretty old fashioned, allbeit that that's a pretty shaky argument. Ah, well, read some about it @quirksmode.org

    0 讨论(0)
  • 2020-11-21 05:34

    If you are using jQuery then:

    HTML:

     <a id="openMap" href="/map/">link</a>
    

    JS:

    $(document).ready(function() {
        $("#openMap").click(function(){
            popup('/map/', 300, 300, 'map');
            return false;
        });
    });
    

    This has the benefit of still working without JS, or if the user middle clicks the link.

    It also means that I could handle generic popups by rewriting again to:

    HTML:

     <a class="popup" href="/map/">link</a>
    

    JS:

    $(document).ready(function() {
        $(".popup").click(function(){
            popup($(this).attr("href"), 300, 300, 'map');
            return false;
        });
    });
    

    This would let you add a popup to any link by just giving it the popup class.

    This idea could be extended even further like so:

    HTML:

     <a class="popup" data-width="300" data-height="300" href="/map/">link</a>
    

    JS:

    $(document).ready(function() {
        $(".popup").click(function(){
            popup($(this).attr("href"), $(this).data('width'), $(this).data('height'), 'map');
            return false;
        });
    });
    

    I can now use the same bit of code for lots of popups on my whole site without having to write loads of onclick stuff! Yay for reusability!

    It also means that if later on I decide that popups are bad practice, (which they are!) and that I want to replace them with a lightbox style modal window, I can change:

    popup($(this).attr("href"), $(this).data('width'), $(this).data('height'), 'map');
    

    to

    myAmazingModalWindow($(this).attr("href"), $(this).data('width'), $(this).data('height'), 'map');
    

    and all my popups on my whole site are now working totally differently. I could even do feature detection to decide what to do on a popup, or store a users preference to allow them or not. With the inline onclick, this requires a huge copy and pasting effort.

    0 讨论(0)
  • 2020-11-21 05:35

    It's a new paradigm called "Unobtrusive JavaScript". The current "web standard" says to separate functionality and presentation.

    It's not really a "bad practice", it's just that most new standards want you to use event listeners instead of in-lining JavaScript.

    Also, this may just be a personal thing, but I think it's much easier to read when you use event listeners, especially if you have more than 1 JavaScript statement you want to run.

    0 讨论(0)
  • 2020-11-21 05:36
    • onclick events run in the global scope and may cause unexpected error.
    • Adding onclick events to many DOM elements will slow down the
      performance and efficiency.
    0 讨论(0)
提交回复
热议问题