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

前端 未结 10 2179
我寻月下人不归
我寻月下人不归 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:46

    Two more reasons not to use inline handlers:

    They can require tedious quote escaping issues

    Given an arbitrary string, if you want to be able to construct an inline handler that calls a function with that string, for the general solution, you'll have to escape the attribute delimiters (with the associated HTML entity), and you'll have to escape the delimiter used for the string inside the attribute, like the following:

    const str = prompt('What string to display on click?', 'foo\'"bar');
    const escapedStr = str
      // since the attribute value is going to be using " delimiters,
      // replace "s with their corresponding HTML entity:
      .replace(/"/g, '"')
      // since the string literal inside the attribute is going to delimited with 's,
      // escape 's:
      .replace(/'/g, "\\'");
      
    document.body.insertAdjacentHTML(
      'beforeend',
      ''
    );

    That's incredibly ugly. From the above example, if you didn't replace the 's, a SyntaxError would result, because alert('foo'"bar') is not valid syntax. If you didn't replace the "s, then the browser would interpret it as an end to the onclick attribute (delimited with "s above), which would also be incorrect.

    If one habitually uses inline handlers, one would have to make sure to remember do something similar to the above (and do it right) every time, which is tedious and hard to understand at a glance. Better to avoid inline handlers entirely so that the arbitrary string can be used in a simple closure:

    const str = prompt('What string to display on click?', 'foo\'"bar');
    const button = document.body.appendChild(document.createElement('button'));
    button.textContent = 'click';
    button.onclick = () => alert(str);

    Isn't that so much nicer?


    The scope chain of an inline handler is extremely peculiar

    What do you think the following code will log?

    let disabled = true;

    Try it, run the snippet. It's probably not what you were expecting. Why does it produce what it does? Because inline handlers run inside with blocks. The above code is inside three with blocks: one for the document, one for the

    , and one for the

Since disabled is a property of the button, referencing disabled inside the inline handler refers to the button's property, not the outer disabled variable. This is quite counter-intuitive. with has many problems: it can be the source of confusing bugs and significantly slows down code. It isn't even permitted at all in strict mode. But with inline handlers, you're forced to run the code through withs - and not just through one with, but through multiple nested withs. It's crazy.

with should never be used in code. Because inline handlers implicitly require with along with all its confusing behavior, inline handlers should be avoided as well.

提交回复
热议问题