这在嵌入脚本时有效。当代码在外部脚本中时,为什么它仅适用于两次单击?
嵌入式案例:
<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);
});
答案 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");
});
你在说:
innerHTML
的元素的title
属性更改为&#39; Goodbye&#39; 添加一个click
事件处理程序:
2.1将ID为innerHTML
的元素的title
属性更改为&#39; Hello&#39;
2.2删除事件click
那么,会发生什么:
第一次点击时
1.1您的h1
将更改为“再见&#39;
1.2并且会有一个新的click
事件处理程序
第二次点击时
2.1它将首先再次触发同一事件,因此您的h1
将更改为“再见”
2.2将会有一个新的click
事件处理程序
2.3 1.2
上添加的先前事件处理程序将被解除
2.4然后,您的h1
将更改回Hello
2.5然后删除它的所有jQuery click
事件处理程序
因此,当您第三次单击时,它就像加载页面时一样,因为放置在HTML代码中的事件处理程序仍将保留,但是所有附加到{{的jQuery事件处理程序1}}被删除了。
那就是说,第3个和第1个相同,第4个和第2个相同,依此类推。
当您停止将事件处理程序附加到HTML代码中并开始通过jQuery附加它时,您的代码将停止工作,因为:
第一次点击时
1.1您的h1
将更改为“再见&#39;
1.2并且会有一个新的h1
事件处理程序
第二次点击时
2.1它将首先再次触发同一事件,因此您的click
将更改为“再见”
2.2将会有一个新的h1
事件处理程序
2.3 click
上添加的先前事件处理程序将被解除
2.4然后,您的1.2
将更改回h1
2.5然后删除它的所有Hello
事件处理程序
如您所见,与上面的示例非常相似。但是有一个很大的区别:当click
发生时,您不再有2.5
个click
事件处理程序,因为您已经删除了所有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);