沒有更好的解。
而且並沒有好與不好,因為DOM的事件機制,原本就是會通過所有有註冊事件的相關節點。
DOM的事件分成兩個capturing跟bubbling兩個phase,例如:
http://jsfiddle.net/fillano/6aLd2zye/5/
點一下test按鈕,你會看到事件經過跟按鈕相關的所有節點,只要他有註冊同一個事件。capturing phase會由外層往內傳播(body->div->button),bubbling phase會由內往外層傳播(button->div->body)。
要影響這個過程,e.cancelBubble=true可以停止bubbling,e.stopPropagation()可以停止整個過程,包含capturing phase。要停止事件的預設動作,則使用e.preventDefault(),例如在拖拉時防止選取文字。
把事件綁在父節點上的做法,叫做delegation,他對於有許多子節點需要處理同樣事件的案例很有幫助,因為不這樣做,你就得一個一個綁上去。要綁在所有非nav
節點比較容易,還是綁在body然後判斷不是nav
比較容易?
var isClosed = false;
$(document).ready(function () {
var trigger = $('.hamburger'),
pageContent = $('.page-content');
pageContent.on("click", function (e) {
var $target = $(e.target);
var webHamburgerBtn = $('#Web_Hamburger_Btn');
var menuPageSideBar = $('#menuPage-sideBar');
if (menuPageSideBar !== $target && menuPageSideBar.has($target).length === 0 && webHamburgerBtn !== $target && webHamburgerBtn.has($target).length === 0) {
if (isClosed === true) {
hamburger_cross();
$('.wrapper').toggleClass('toggled');
}
}
});
trigger.click(function () {
hamburger_cross();
});
function hamburger_cross() {
if (isClosed === true) {
trigger.removeClass('is-open');
trigger.addClass('is-closed');
isClosed = false;
} else {
trigger.removeClass('is-closed');
trigger.addClass('is-open');
isClosed = true;
}
}
$('[data-toggle="offcanvas"]').click(function () {
$('.wrapper').toggleClass('toggled');
});
});
$().on("focusout",handler);
或
$().focusout(...);
參考:https://api.jquery.com/focusout/
使用stopPropagation()停止往上散播事件:
https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation
例如:
$(document).bind('click', function(e) {
var e = e || window.event; //瀏覽器兼容性
e.stopPropagation();
....
其實你想要的大約知道。只是很難辦到。
畢竟click事件,也是需要有一個元件來做判發的。
所以大多數很少人會去做點其它地方觸發。
就如msgbox雖然也是有點其它地方就關閉。但它的原理則是會在觸發視窗的同時,覆蓋一個透明或半透明的元件在全畫面上。方便處理點其它地方的事件。
上面的寫法,其實不外乎如下的做法
1.欄所有的click事件。
2.建立body的click事件。
3.建立document元件click事件
但無論任何方式,一個目標是無法避免的。就是你一定要達到點任意地方就要觸發。
如果無論如何都不能去避免這件事的話。建議還是乖乖的在body或是用dom的click事件處理吧。
有一種做法,就是把 nav 包在全螢幕的 wraper 裡。
展開 wraper 的時候,nav會一起展開。
也就是modal的作法。
https://getbootstrap.com/docs/4.1/components/modal/#live-demo
算是僅達成你想要的效果,但是轉個彎的作法。
真的要都如你所表達的話,就請參閱 fillano等寫的。