JavaScript 浏览器默认行为
许多事件会自动触发浏览器执行某些行为,如点击一个链接会触发导航 navigation 到该 URL,点击表单的提交按钮会触发提交表单内容到服务器的行为。
如果我们希望使用 JavaScript 自定义处理一个事件的方式,那么通常不希望发生相应的浏览器默认行为,我们可以阻止浏览器这种默认行为的执行
- (主流方式)通过事件对象的方法
event,preventDefault()
阻止浏览器执行事件相关的默认行为 - 如果处理程序是使用
on<event>
(而不是addEventListener
)分配的,那返回false
也同样有效。
<!-- 阻止点击链接触发导航 navigation 的默认行为 -->
<a href="/" onclick="return false">Click here</a>
<!-- 另一种方法 -->
<a href="/" onclick="event.preventDefault()">here</a>
⚠️ 事件处理程序返回的值通常会被忽略,唯一的例外是从使用 on<event>
分配的处理程序中返回的 return false
,除此以为在所有其他情况下 return
值都会被忽略,返回 true
也没有意义。
💡 如果对于 on<event>
并非设置为 return false
而是还进行了其他处理的函数,则需要使用 return function
来表示,因为当浏览器读取 on*
特性(attribute)时,会根据其内容创建对应的处理程序,如对于 onclick="handler()"
会创建函数
function(event) {
handler();
}
由于创建的函数没有返回值,因此默认为 undefined
,因此设置为 <a href="https://w3.org" onclick="return handler()">w3.org</a>
即相当于 return false
阻止浏览器默认行为
passive
方法 elem.addEventListener(event, handler, [options]);
的可选项 passive: true
向浏览器发出信号,表明处理程序将不会调用 preventDefault()
因此浏览器可以「放心大胆」地立即执行相关事件的默认行为。
这对于某些移动端的事件,如 touchstart
和 touchmove
很有用,passive: true
选项告诉浏览器处理程序不会取消滚动,然后浏览器立即滚动页面以提供最大程度的流畅体验,对于某些浏览器(Firefox,Chrome),默认情况下 touchstart
和 touchmove
事件的 passive
为 true
。
defaultPrevented
通过方法 event.preventDefault()
阻止浏览器默认行为,如果默认行为被阻止,那么对象的 event.defaultPrevented
属性为 true
。可以使用 event.defaultPrevented
来代替 event.stopPropagation()
通知其他事件处理程序该事件已经被处理,通过条件判断语句可以「阻止」祖先链上相关重复的事件处理程序执行,但并不阻止事件冒泡因此其他的事件处理程序依然可以触发。
<p>Right-click for the document menu (added a check for event.defaultPrevented)</p>
<button id="elem">Right-click for the button menu</button>
<script>
elem.oncontextmenu = function(event) {
event.preventDefault(); // 阻止浏览器默认行为
alert("Button context menu");
};
document.oncontextmenu = function(event) {
if (event.defaultPrevented) return; // 根据事件对象的 defaultPrevented 是否为 true 控制祖先链事件处理程序的执行
event.preventDefault();
alert("Document context menu");
};
let click = 0;
document.oncontextmenu = function() {
click++; // 即使 oncontextmenu 事件的浏览器默认行为被阻止,该祖先链上的事件处理器也会执行,因为事件依然可以冒泡
};
</script>
Tip
浏览器在 contextmenu
事件(单击鼠标右键)发生时,会显示带有标准选项的上下文菜单,我们可以阻止该浏览器默认行为并显示我们自定义的菜单