onclick=“” vs event handler

前端 未结 8 2151
伪装坚强ぢ
伪装坚强ぢ 2020-11-22 00:20

If I want a function to be executed, I prefer doing inline js:

Click me

becaus

相关标签:
8条回答
  • 2020-11-22 00:58

    Despite what other people may think, I think there are redeeming value to inlining listeners in markup. Specifically, it gives you a lot more freedom to modifying the DOM nodes. If you're adding listeners though JavaScript, the listeners are lost when you replace the innerHTML of any parent nodes. If you're inlining the listeners in markup, you can clone the node, make modifications to it, then replace the original node with the node you just cloned and modified.

    Perhaps it's better to describe it in a specific use case. I want to make changes to multiple part of the document without triggering reflow multiple times. So in this case, I can clone the node, make any change to it (no reflow since its detached), then replace the previous node with the modified one (triggering one reflow). With inlined listeners, this prevents any listeners from getting lost during the replacement.

    0 讨论(0)
  • 2020-11-22 00:59

    One big argument against inline event handlers, and the argument that is addressed by the other answers here is the separation of presentation and logic.

    However, there is actually a bigger problem IMO: The somehow elusive way how inline event handlers are evaluated.

    As you may know, the content of the on* attributes will be used as body of the event handler function. But what characteristics does this function have?

    One of the surprising ones is that properties of some ancestor elements and of the element itself are in the scope of the inline event handler.

    <form>
        <input name="foo" />
        <button type="button" onclick="console.log(foo); console.log(window.foo);">
            Click me
        </button>
        <div onclick="console.log(foo);">Click me as well!</div>
    </form>

    Clicking the button logs

    <input name="foo"></input>
    undefined
    

    in the console. The fact that window.foo is undefined tells you that there is no global variable foo. So where does the variable foo come from? Why does console.log(foo) log the input element and not throw a reference error?
    Because the properties of the form element are in the scope of the event handler and the form element has a property for each named form control element it contains. You can easily test this with console.log(document.querySelector('form').foo).

    Now, clicking the div element actually throws a reference error:

    ReferenceError: foo is not defined

    So apparently the form element is only in scope of form control elements, not any descendant. How confusing is that?

    Similarly, the properties of the document object are also in the scope of inline event handlers, which can lead to some surprising bugs (did you know that document has a property plugins?).

    How exactly inline event handlers are evaluated is formalized in the HTML5 spec. Have a loop at step 10 in particular where he scope chain creation is described.


    Conclusion:

    Because of this implicit connection between elements and inline event handlers, bugs can be really hard to track. It's of course fine to use inline event handlers if you just want to test something. But using them in production code comes with a higher maintenance cost.

    The articles at quirksmode.org explain the different ways of binding event handlers and their (dis)advantages very well.

    0 讨论(0)
提交回复
热议问题