点击事件的jQuery开/关方法从外部脚本失败

时间:2015-09-26 02:15:45

标签: javascript jquery

这在嵌入脚本时有效。当代码在外部脚本中时,为什么它仅适用于两次单击?

嵌入式案例:

<html>    
<head>
  <script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
</head>    
<body>
  <h1 id="title" onclick="sayGoodbye();"> Hello </h1>
</body>    
<script type="text/javascript">
  function sayGoodbye() {
    console.log("goodbye");
    $("#title").html("Goodbye");
    $("#title").click(function() {
      $("#title").html("Hello");
      $("#title").off("click");
    });
  };
</script>    
</html>

外部文件测试如下:

<body>
  <h1 id="title"> Hello </h1>
</body>

外部Javascript文件:

function sayGoodbye() {
  console.log('goodbye');
  $('#title').html('Goodbye');
  $('#title').click(function() {
    $('#title').html('Hello');
    $('#title').off('click');
  });
};

$(function(){
   $('#title').on('click', sayGoodbye);
});

2 个答案:

答案 0 :(得分:1)

该问题与外部或嵌入的文件无关。

您已经更改了代码,这就是它停止工作的原因。您可以将HTML代码与原始代码<h1 id="title" onclick="sayGoodbye();"> Hello </h1>保持一致。

因为你已经改变了,这就是它不再工作的原因。

通过Javascript&#39; addEventListener或jQuery&#39; on添加事件侦听器时,必须始终传递函数引用,而不是函数执行。如果您使用(),则会立即调用该函数,并将其返回的值传递给您正在调用的其他函数。

例如,如果我这样做:

function num() {
  return 5;
}

console.log(num);   // it will log 'function num()'
console.log(num()); // it will log 5

由于您的sayGoodbye函数不返回任何内容,因此传递给jQuery&#39 {s} on的值将为undefined

function num() {
   var y = 5;
   y = y + 10;
}

console.log(num);   // it will log 'function num() '
console.log(num()); // it will log 'undefined'

当您输入HTML onclick="sayGoodbye();"时,您实际上在说:

Element.onclick = function() {
  sayGoodbye();
}

它会自动将您的代码包装到匿名函数中,并将其作为对事件的引用传递。

<强>铊组成; dr

您的代码无法使用,因为您正在使用:

$('#title').on('click', sayGoodbye());

立即评估/调用函数,因为括号存在。

相反,您应该按名称提供回调函数:

$('#title').on('click', sayGoodbye);

或者作为匿名函数:

$('#title').on('click', function() {
  sayGoodbye();
});

<强>更新

更改问题后,这似乎是另一个简单的问题。

您在哪里定义<script src="externalscript.js"></script>

您应将其放置在嵌入式设备所在的位置。如果您已将其添加到head标记中,则会在加载h1#test之前对其进行评估,然后,它将无法找到该元素,并且不会对其进行评估。 t添加事件监听器。

但是,如果您确实需要/需要将其放在head标记内,那么您必须将代码包装到load事件侦听器中。如果使用vanilla Javascript,那将是:

document.addEventListener('DOMContentLoaded', function() {
  // your code
});

但是,既然你正在使用jQuery,你可以使用$(document).ready

$(document).ready(function() {
  // your code
});

并且有一个简写,它只是包含在$();中:

$(function() {
  // your code
});

注意:我刚刚意识到你最大的问题是你不了解做<h1 id="title" onclick="sayGoodbye();"> Hello </h1>和通过jQuery添加事件处理程序之间的区别。

你的第一个例子正如你期望的那样工作,因为当你这样做时:

$("#title").html("Goodbye");
$("#title").click(function() {
  $("#title").html("Hello");
  $("#title").off("click");
});

你在说:

  1. 将ID为innerHTML的元素的title属性更改为&#39; Goodbye&#39;
  2. 添加一个click事件处理程序:

    2.1将ID为innerHTML的元素的title属性更改为&#39; Hello&#39;

    2.2删除事件click

  3. 的所有 jQuery 事件处理程序

    那么,会发生什么:

    1. 第一次点击时

      1.1您的h1将更改为“再见&#39;

      1.2并且会有一个新的click事件处理程序

    2. 第二次点击时

      2.1它将首先再次触发同一事件,因此您的h1将更改为“再见”

      2.2将会有一个新的click事件处理程序

      2.3 1.2上添加的先前事件处理程序将被解除

      2.4然后,您的h1将更改回Hello

      2.5然后删除它的所有jQuery click事件处理程序

    3. 因此,当您第三次单击时,它就像加载页面时一样,因为放置在HTML代码中的事件处理程序仍将保留,但是所有附加到{{的jQuery事件处理程序1}}被删除了。

      那就是说,第3个和第1个相同,第4个和第2个相同,依此类推。

      当您停止将事件处理程序附加到HTML代码中并开始通过jQuery附加它时,您的代码将停止工作,因为:

      1. 第一次点击时

        1.1您的h1将更改为“再见&#39;

        1.2并且会有一个新的h1事件处理程序

      2. 第二次点击时

        2.1它将首先再次触发同一事件,因此您的click将更改为“再见”

        2.2将会有一个新的h1事件处理程序

        2.3 click上添加的先前事件处理程序将被解除

        2.4然后,您的1.2将更改回h1

        2.5然后删除它的所有Hello事件处理程序

      3. 如您所见,与上面的示例非常相似。但是有一个很大的区别:当click发生时,您不再有2.5click事件处理程序,因为您已经删除了所有h1那里。

        会发生这种情况,因为当您只将一个参数传递给jQuery的off方法时,您就会说&#34;删除该类型的所有jQuery事件处理程序事件&#34; (在这种情况下,click)。因此,它将删除附加到sayGoodBye的事件处理程序和您使用匿名函数创建的事件处理程序。

        在第一个示例中,它没有发生,因为jQuery不知道您通过HTML代码附加的事件,因此它永远不会删除它,并且您的代码按照您的方式工作期望的。

        因此,如果您只想使用jQuery,那么您的代码应该是:

        $(function(){
          function sayGoodbye() {
            $('#title')
              .html('Goodbye')
              .off('click', sayGoodbye)
              .on('click', sayHello);
          }
        
          function sayHello() {
            $('#title')
              .html('Hello')
              .off('click', sayHello)
              .on('click', sayGoodbye);
          }
        
          $('#title').on('click', sayGoodbye);
        });
        

答案 1 :(得分:0)

传递函数 引用 的语法不正确。

$('#title').on('click',sayGoodbye());

由于(),将立即调用该函数。

更改为:

$('#title').on('click',sayGoodbye);