背景
前些天在 IE 浏览器测试功能的时候,点击某处功能触发函数时,alert 了一个错误提示,接着点击 alert 的确定按钮,页面发生了跳转,并仅展示了 false,结果就如下图。
一开始没留意到是 a 标签,增加了不少排查时间。如今问题处理完了,然后做个了一些对比测试,所以梳理并记录一下。
正文
先贴个测试代码
<html>
<head>
<title>test</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<a href="javascript:test1();">测试按钮1.1</a>
<a href="javascript:test2();">测试按钮1.2</a>
<a href="javascript:test4();">测试按钮1.3</a>
<br/>
<a href="javascript:test1();test3();">测试按钮1.1.1</a>
<a href="javascript:test2();test3();">测试按钮1.2.1</a>
<br/>
<br/>
<br/>
<a href="https://www.baidu.com/" onclick="test1();">测试按钮2.1</a>
<a href="https://www.baidu.com/" onclick="test2();">测试按钮2.2</a>
<a href="https://www.baidu.com/" onclick="return test2();">测试按钮2.3</a>
<br/>
<a href="https://www.baidu.com/" onclick="test1();test3();">测试按钮2.1.1</a>
<a href="https://www.baidu.com/" onclick="return test2();test3()">测试按钮2.3.1</a>
<br/>
<br/>
<br/>
<a href="https://www.baidu.com/" onclick="test5();">测试按钮3.1</a>
<script>
function test1(){debugger;
console.log("11111");
return;
}
function test2(){debugger;
console.log("22222");
return false;
}
function test3(){debugger;
console.log("33333")
}
function test4(){debugger;
if(true){return false;}
console.log("4444");
}
function test5(){debugger;
console.log("55555");
if(true){
window.event.returnValue = false;
//return;
}
console.log("test5 end");
}
</script>
</body>
</html>
测试1
我们遇到的问题就是 1.2,a 标签的 href 直接调用函数,然后函数有 return false,结果就是发生了页面跳转,并且仅展示了 false。
如果在谷歌点击 1.2 按钮,是不会发生页面跳转的。
我们当时的解决办法是将函数里面的 return false,修改成为 return,就是说去掉 false,问题就解决了。IE 和 google 浏览器都正常。
思考
点击 a 标签除了触发函数以外,还要触发一个默认事件,这个默认事件就是执行页面跳转。
return 和 return false 的作用都是用来取消默认事件这个动作。但它两的区别是后者带有返回值,返回值就是 false。
那为什么 1.1 不会跳转,而 1.2 发生了跳转呢?
如果在 href 里面增加 test3() 函数,并都打上断点,你会发现点击任何一个按钮,都会触发两个函数。
<a href="javascript:test1();test3();">测试按钮1.1.1</a>
<a href="javascript:test2();test3();">测试按钮1.2.1</a>
所以,1.1 看似解决了问题,但实际上是因为 test1() 的 return 没有返回值。
我们正常逻辑是当 test1() return false 之后,后面的所有逻辑不再执行,但是现在实际上是执行了 test3() 的逻辑。
然后我们会发现 1.2.1,原本 test2() return false 是发生跳转的,但结果接着执行完 test3() 后,没有发生跳转。
到这里我有一个猜想,href=“javascript:test2();test3();” 类似一个方法块,方法块里有两个子方法。有点像 JAVA 里面的 main 方法,然后 main 方法分别调用不同的 static 方法。
后来补了测试 1.3,结论是:return false 在当前方法(test4())内有效,不会继续执行本方法下面的逻辑。
测试2
测试 2 的写法是我们比较常见的,有一个 onclick 事件。
事实上 2.1,2.2 IE 和谷歌都发生了跳转,这是无容置疑的。但是 2.3 阻止了页面跳转。
所以 2.3 的原因有可能跟上面的猜想有关,把 onclick 看作一个 main 方法,test2() 返回 false,到 main 方法的时候接收到了这个返回值,所以实际上 main 方法也是 return false。
根据上面想法,写了测试 2.1.1,2.3.1,而且得到了证实。如果上面想法不好理解的话,写个JAVA代码。
public static void main(String[] args) {
Boolean b = test2();
if(!b) return;
test3();
}
public static boolean test2() {
System.out.println("22222");
return false;
}
public static void test3() {
System.out.println("33333");
}
当 test2 return false 后,main 方法也得到了 return false,而 return 对当前方法有效,所以阻断了后面的执行逻辑,即 test3 不再执行。
所以测试 2 的结论就是 onclick 加上 return 可以有效阻止页面跳转 。
最后
网上说 window.event.returnValue = false 也可以阻止页面跳转,但是我没有尝试成功。
也看见有人说 onclick 加上 return 等同于 window.event.returnValue = false。
我还看到一种写法 onclick = “test3();return false;”,这种写法是一律阻止页面跳转。所以比较好的实现方式是 2.3 或者 2.3.1。