onclick =""vs事件处理程序

Joh*_*han 33 javascript event-handling inline-code

如果我想要执行一个函数,我更喜欢使用内联js:

<p id="element" onclick="doSomething();">Click me</p>
Run Code Online (Sandbox Code Playgroud)

因为它更容易调试.

但是,我听到人们说不使用内联js,并做:

document.getElementById('element').onclick = doSomething;
Run Code Online (Sandbox Code Playgroud)

为什么推荐使用js事件监听器?

Fel*_*ing 39

反对内联事件处理程序的一个重要论点,以及其他答案解决的论点是表示和逻辑的分离.

然而,IMO实际上存在一个更大的问题:如何评估内联事件处理程序的难以理解的方式.

您可能知道,on*属性的内容将用作事件处理函数的主体.但这个功能有什么特点?

其中一个令人惊讶的是,一些祖先元素元素本身的属性属于内联事件处理程序的范围.

<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>
Run Code Online (Sandbox Code Playgroud)

单击button日志

<input name="foo"></input>
undefined
Run Code Online (Sandbox Code Playgroud)

在控制台中.这事实上window.fooundefined告诉你,有没有全局变量foo.那么变量foo来自哪里?为什么console.log(foo)记录输入元素而不抛出引用错误?
因为form元素的属性在事件处理程序的范围内,并且form元素具有它包含的每个命名表单控件元素的属性.您可以轻松地测试它console.log(document.querySelector('form').foo).

现在,单击该div元素实际上会引发一个引用错误:

ReferenceError: foo is not defined

所以显然form元素只在形式控制元素的范围内,而不是任何后代.这有多令人困惑?

类似地,对象的属性document也在内联事件处理程序的范围内,这可能会导致一些令人惊讶的错误(你知道它document有一个属性plugins?).

如何评估内联事件处理程序是在HTML5规范中形式化的.在步骤10中有一个循环,特别是在描述范围链创建的地方.


结论:

由于元素和内联事件处理程序之间存在这种 隐式连接,因此很难跟踪错误.如果你只想测试一些内容,那么使用内联事件处理程序当然很好.但是在生产代码中使用它们会带来更高的维护成本.

quirksmode.org上的文章解释了绑定事件处理程序的不同方法及其(dis)优势.


Lee*_*eeR 13

基本上它与整体保持一致我相信.因此,请将HTML/CSS/JS全部分开.它使您的HTML更整洁,我认为更容易导航.

然后当/如果你需要进行大的更改时,你有足够的空间,无论如何都必须将内联JS转换为外部文件,或者如果你想将相同的函数应用于多个按钮,那么它的代码就更少了.更少的代码是一个更幸福的地方

如果你的JS文件正确,并且有完整的文档记录,那么由外部人员导航它们就是eaiser


bre*_*nac 5

避免内联 JavaScript 的原因有很多,其中最重要的原因之一可能是代码的可维护性。

一个简单的例子(我使用 jQuery 只是为了演示目的)。

<p class="element" onclick="doSomething();">Click me</p>
<p class="element" onclick="doSomething();">Click me</p>
<p class="element" onclick="doSomething();">Click me</p>
<p class="element" onclick="doSomething();">Click me</p>
<p class="element" onclick="doSomething();">Click me</p>
<p class="element" onclick="doSomething();">Click me</p>
Run Code Online (Sandbox Code Playgroud)

如果您突然收到更改所有段落以执行另一个功能的请求怎么办?在您的示例中,您必须手动更改 HTML 代码中的所有内容。但是,如果您选择将 HTML 与 JavaScript 分开,您可以简单地这样做。

<p class="element">Click me</p>
<p class="element">Click me</p>
<p class="element">Click me</p>
<p class="element">Click me</p>
<p class="element">Click me</p>
<p class="element">Click me</p>

$('.element').bind('click', doSomethingElse);
Run Code Online (Sandbox Code Playgroud)

HTML 代码也更清晰,这使设计人员可以专注于设计,而不必担心他们在处理涉及其他人的项目时可能会实际破坏某些内容。

编辑:为我的评论提供示例。

Project = {
    // All the variables/constants/objects that need to be globally accessible inside the Project object.

    init : function(){
        // Main entry point...
        this.MainMenu.init();

        // Rest of the code which should execute the moment Project is initiated.
    }
}

Project.MainMenu = {
    // All the variables/constants/objects that need to be accessible only to MainMenu.

    init : function(){ // Is run immediatelly by Project.init()
        // Event handlers relevant to the main menu are bound here

        // Rest of the initialization code
    }
}

Project.SlideShow = {
    // All the variables/constants/objects that need to be accessible only to SlideShow.

    init : function(){ // Is run only on pages that really require it.
        // Event handlers for the slideshow.
    }
}
Run Code Online (Sandbox Code Playgroud)