当我在侧边栏外单击时关闭侧边栏
Close a sidebar when I click outside of it
我试图在点击边栏外部时关闭它。
我添加了一个条件,仅在它打开时关闭它 (nav_active
),但我遗漏了一些东西。
预期的行为是在我单击红框内部或外部时显示警报。
解后编辑
我刚刚意识到第一次点击会在外面,所以当我删除活动 class 时,滑块将永远不会显示
"use strict";
var burger = document.querySelector('.burger');
var nav = document.querySelector('.nav_links');
burger.addEventListener('click', function () {
nav.classList.toggle('nav_active');
});
if (nav.classList.contains("nav_active")) {
window.addEventListener('click', function(e) {
nav.classList.remove('nav_active');
});
}
.nav_home, .nav_links, .nav_buttons, .nav_list {
display: inline-block;
vertical-align: middle;
}
.burger {
width: 2.4rem;
height: 2.4rem;
margin: auto 0;
cursor: pointer;
background: black;
}
.nav_list a:hover {
text-decoration: line-through !important;
}
.nav_links {
display: block;
z-index: 0;
position: absolute;
right: 0rem;
width: 80%;
margin-right: 0.1rem;
border-left: 0.1rem solid;
background: red;
}
.nav_item {
display: block;
}
.nav_list {
display: block;
a {
display: block;
}
span {
display: none;
}
}
.nav_active {
background: blue;
display: inline-block;
}
<header id="header">
<div class="header container">
<div class="nav_links">
<h5 class="nav_list">
<span class="noselect">⁄</span>
</h5>
<div class="nav_buttons">
<h5 class="theme-label"></h5>
</div>
</div>
<div class="burger"></div>
</div>
</header>
您只需将代码移动到您的侦听器中 - 我重新格式化了您将变量分配给函数的方式。最后,我在关闭时删除了 window
事件侦听器。
"use strict";
var burger = document.querySelector('.burger');
var nav = document.querySelector('.nav_links');
const navSlide = () => {
burger.addEventListener('click', function(ev) {
nav.classList.toggle('nav_active');
if (nav.classList.contains("nav_active")) {
window.addEventListener('click', captureClick);
console.log("ADDED WINDOW LISTENER")
} else {
// remove the window event listener
window.removeEventListener('click', captureClick);
console.log("REMOVED WINDOW LISTENER")
}
});
};
const captureClick = (e) => {
if (nav.contains(e.target)) {
alert("Clicked in Box");
} else {
alert("Clicked outside Box");
}
}
navSlide();
.nav_home,
.nav_links,
.nav_buttons,
.nav_list {
display: inline-block;
vertical-align: middle;
}
.burger {
width: 2.4rem;
height: 2.4rem;
margin: auto 0;
cursor: pointer;
background: black;
}
.nav_list a:hover {
text-decoration: line-through !important;
}
.nav_links {
display: block;
z-index: 0;
position: absolute;
right: 0rem;
width: 80%;
margin-right: 0.1rem;
border-left: 0.1rem solid;
background: red;
}
.nav_item {
display: block;
}
.nav_list {
display: block;
a {
display: block;
}
span {
display: none;
}
}
.nav_active {
display: inline-block;
}
<header id="header">
<div class="header container">
<div class="nav_links">
<h5 class="nav_list">
<span class="noselect">⁄</span>
</h5>
<div class="nav_buttons">
<h5 class="theme-label"></h5>
<input class="themeSwitch" type="checkbox" id="switch" name="theme" />
<label class="toggle" for="switch"></label>
<label class="switch" for="switch"></label>
</div>
</div>
<div class="burger"></div>
</div>
</header>
您的第二个事件侦听器永远不会被添加,因为在函数调用时 .nav_links
没有 class .nav_active
。因此,您必须将 if (nav.classList.contains("nav_active"))
移动到该侦听器的处理函数中。
工作示例:
(为了演示,我在活动时将背景更改为绿色)
"use strict";
var burger = document.querySelector('.burger');
var nav = document.querySelector('.nav_links');
var navSlide = function() {
burger.addEventListener('click', function() {
nav.classList.toggle('nav_active');
console.log("Clicked on Burger");
});
window.addEventListener('click', function(e) { // i exchanged
if (nav.classList.contains("nav_active")) { // these 2 lines
if (nav.contains(e.target)) {
console.log("Clicked in Box");
}
else {
console.log("Clicked outside Box");
}
} // and
}); // these
};
navSlide();
.nav_home,
.nav_links,
.nav_buttons,
.nav_list {
display: inline-block;
vertical-align: middle;
}
.burger {
width: 2.4rem;
height: 2.4rem;
margin: auto 0;
cursor: pointer;
background: black;
}
.nav_list a:hover {
text-decoration: line-through !important;
}
.nav_links {
display: block;
z-index: 0;
position: absolute;
right: 0rem;
width: 80%;
margin-right: 0.1rem;
border-left: 0.1rem solid;
background: red;
}
.nav_item {
display: block;
}
.nav_list {
display: block;
a {
display: block;
}
span {
display: none;
}
}
.nav_active {
display: inline-block;
background-color: green;
}
<header id="header">
<div class="header container">
<div class="nav_links">
<h5 class="nav_list">
<span class="noselect">⁄</span>
</h5>
<div class="nav_buttons">
<h5 class="theme-label"></h5>
<input class="themeSwitch" type="checkbox" id="switch" name="theme" />
<label class="toggle" for="switch"></label>
<label class="switch" for="switch"></label>
</div>
</div>
<div class="burger"></div>
</div>
</header>
但我认为当您只想切换菜单时,您可以简单地使用一个事件侦听器(及其处理程序)进行所有操作。因此,您只需处理两种情况:点击是在 burger
上还是在 nav
(和汉堡包)之外。第三种情况(最后一个else
)只是为了演示。
工作示例:
(我省略了 navSlide()
函数)
"use strict";
var burger = document.querySelector('.burger');
var nav = document.querySelector('.nav_links');
window.addEventListener('click', function(e) {
if (e.target.classList.contains('burger')) {
nav.classList.toggle('nav_active');
console.log("Clicked on Burger");
}
else if (!nav.contains(e.target)) {
nav.classList.remove('nav_active');
console.log("Clicked outside Box");
}
else {
console.log("Clicked in Box");
}
});
.nav_home,
.nav_links,
.nav_buttons,
.nav_list {
display: inline-block;
vertical-align: middle;
}
.burger {
width: 2.4rem;
height: 2.4rem;
margin: auto 0;
cursor: pointer;
background: black;
}
.nav_list a:hover {
text-decoration: line-through !important;
}
.nav_links {
display: block;
z-index: 0;
position: absolute;
right: 0rem;
width: 80%;
margin-right: 0.1rem;
border-left: 0.1rem solid;
background: red;
}
.nav_item {
display: block;
}
.nav_list {
display: block;
a {
display: block;
}
span {
display: none;
}
}
.nav_links.nav_active {
display: inline-block;
background-color: green;
}
<header id="header">
<div class="header container">
<div class="nav_links">
<h5 class="nav_list">
<span class="noselect">⁄</span>
</h5>
<div class="nav_buttons">
<h5 class="theme-label"></h5>
<input class="themeSwitch" type="checkbox" id="switch" name="theme" />
<label class="toggle" for="switch"></label>
<label class="switch" for="switch"></label>
</div>
</div>
<div class="burger"></div>
</div>
</header>
如果您希望仅在菜单打开 (nav.classList.contains("nav_active")
) 时添加第二个事件侦听器,否则将其删除,则必须将其嵌套到第一个侦听器的处理程序(匿名函数)中。您必须将第二个处理程序定义为单独的函数(此处 checkClickLocation()
),因为 removeEventListener()
需要函数引用(此处 checkClickLocation
)作为参数来停止它。
工作示例:
"use strict";
var burger = document.querySelector('.burger');
var nav = document.querySelector('.nav_links');
function checkClickLocation(e) {
if (!nav.contains(e.target)) {
nav.classList.remove('nav_active');
window.removeEventListener('click', checkClickLocation);
console.log("Clicked outside Box");
}
else {
console.log("Clicked in Box");
}
}
burger.addEventListener('click', function(e) {
e.stopPropagation()
nav.classList.toggle('nav_active');
if (nav.classList.contains("nav_active")) {
window.addEventListener('click', checkClickLocation);
}
else {
window.removeEventListener('click', checkClickLocation);
}
console.log("Clicked on Burger");
});
.nav_home,
.nav_links,
.nav_buttons,
.nav_list {
display: inline-block;
vertical-align: middle;
}
.burger {
width: 2.4rem;
height: 2.4rem;
margin: auto 0;
cursor: pointer;
background: black;
}
.nav_list a:hover {
text-decoration: line-through !important;
}
.nav_links {
display: block;
z-index: 0;
position: absolute;
right: 0rem;
width: 80%;
margin-right: 0.1rem;
border-left: 0.1rem solid;
background: red;
}
.nav_item {
display: block;
}
.nav_list {
display: block;
a {
display: block;
}
span {
display: none;
}
}
.nav_active {
display: inline-block;
background-color: green;
}
<header id="header">
<div class="header container">
<div class="nav_links">
<h5 class="nav_list">
<span class="noselect">⁄</span>
</h5>
<div class="nav_buttons">
<h5 class="theme-label"></h5>
<input class="themeSwitch" type="checkbox" id="switch" name="theme" />
<label class="toggle" for="switch"></label>
<label class="switch" for="switch"></label>
</div>
</div>
<div class="burger"></div>
</div>
</header>
我试图在点击边栏外部时关闭它。
我添加了一个条件,仅在它打开时关闭它 (nav_active
),但我遗漏了一些东西。
预期的行为是在我单击红框内部或外部时显示警报。
解后编辑 我刚刚意识到第一次点击会在外面,所以当我删除活动 class 时,滑块将永远不会显示
"use strict";
var burger = document.querySelector('.burger');
var nav = document.querySelector('.nav_links');
burger.addEventListener('click', function () {
nav.classList.toggle('nav_active');
});
if (nav.classList.contains("nav_active")) {
window.addEventListener('click', function(e) {
nav.classList.remove('nav_active');
});
}
.nav_home, .nav_links, .nav_buttons, .nav_list {
display: inline-block;
vertical-align: middle;
}
.burger {
width: 2.4rem;
height: 2.4rem;
margin: auto 0;
cursor: pointer;
background: black;
}
.nav_list a:hover {
text-decoration: line-through !important;
}
.nav_links {
display: block;
z-index: 0;
position: absolute;
right: 0rem;
width: 80%;
margin-right: 0.1rem;
border-left: 0.1rem solid;
background: red;
}
.nav_item {
display: block;
}
.nav_list {
display: block;
a {
display: block;
}
span {
display: none;
}
}
.nav_active {
background: blue;
display: inline-block;
}
<header id="header">
<div class="header container">
<div class="nav_links">
<h5 class="nav_list">
<span class="noselect">⁄</span>
</h5>
<div class="nav_buttons">
<h5 class="theme-label"></h5>
</div>
</div>
<div class="burger"></div>
</div>
</header>
您只需将代码移动到您的侦听器中 - 我重新格式化了您将变量分配给函数的方式。最后,我在关闭时删除了 window
事件侦听器。
"use strict";
var burger = document.querySelector('.burger');
var nav = document.querySelector('.nav_links');
const navSlide = () => {
burger.addEventListener('click', function(ev) {
nav.classList.toggle('nav_active');
if (nav.classList.contains("nav_active")) {
window.addEventListener('click', captureClick);
console.log("ADDED WINDOW LISTENER")
} else {
// remove the window event listener
window.removeEventListener('click', captureClick);
console.log("REMOVED WINDOW LISTENER")
}
});
};
const captureClick = (e) => {
if (nav.contains(e.target)) {
alert("Clicked in Box");
} else {
alert("Clicked outside Box");
}
}
navSlide();
.nav_home,
.nav_links,
.nav_buttons,
.nav_list {
display: inline-block;
vertical-align: middle;
}
.burger {
width: 2.4rem;
height: 2.4rem;
margin: auto 0;
cursor: pointer;
background: black;
}
.nav_list a:hover {
text-decoration: line-through !important;
}
.nav_links {
display: block;
z-index: 0;
position: absolute;
right: 0rem;
width: 80%;
margin-right: 0.1rem;
border-left: 0.1rem solid;
background: red;
}
.nav_item {
display: block;
}
.nav_list {
display: block;
a {
display: block;
}
span {
display: none;
}
}
.nav_active {
display: inline-block;
}
<header id="header">
<div class="header container">
<div class="nav_links">
<h5 class="nav_list">
<span class="noselect">⁄</span>
</h5>
<div class="nav_buttons">
<h5 class="theme-label"></h5>
<input class="themeSwitch" type="checkbox" id="switch" name="theme" />
<label class="toggle" for="switch"></label>
<label class="switch" for="switch"></label>
</div>
</div>
<div class="burger"></div>
</div>
</header>
您的第二个事件侦听器永远不会被添加,因为在函数调用时 .nav_links
没有 class .nav_active
。因此,您必须将 if (nav.classList.contains("nav_active"))
移动到该侦听器的处理函数中。
工作示例:
(为了演示,我在活动时将背景更改为绿色)
"use strict";
var burger = document.querySelector('.burger');
var nav = document.querySelector('.nav_links');
var navSlide = function() {
burger.addEventListener('click', function() {
nav.classList.toggle('nav_active');
console.log("Clicked on Burger");
});
window.addEventListener('click', function(e) { // i exchanged
if (nav.classList.contains("nav_active")) { // these 2 lines
if (nav.contains(e.target)) {
console.log("Clicked in Box");
}
else {
console.log("Clicked outside Box");
}
} // and
}); // these
};
navSlide();
.nav_home,
.nav_links,
.nav_buttons,
.nav_list {
display: inline-block;
vertical-align: middle;
}
.burger {
width: 2.4rem;
height: 2.4rem;
margin: auto 0;
cursor: pointer;
background: black;
}
.nav_list a:hover {
text-decoration: line-through !important;
}
.nav_links {
display: block;
z-index: 0;
position: absolute;
right: 0rem;
width: 80%;
margin-right: 0.1rem;
border-left: 0.1rem solid;
background: red;
}
.nav_item {
display: block;
}
.nav_list {
display: block;
a {
display: block;
}
span {
display: none;
}
}
.nav_active {
display: inline-block;
background-color: green;
}
<header id="header">
<div class="header container">
<div class="nav_links">
<h5 class="nav_list">
<span class="noselect">⁄</span>
</h5>
<div class="nav_buttons">
<h5 class="theme-label"></h5>
<input class="themeSwitch" type="checkbox" id="switch" name="theme" />
<label class="toggle" for="switch"></label>
<label class="switch" for="switch"></label>
</div>
</div>
<div class="burger"></div>
</div>
</header>
但我认为当您只想切换菜单时,您可以简单地使用一个事件侦听器(及其处理程序)进行所有操作。因此,您只需处理两种情况:点击是在 burger
上还是在 nav
(和汉堡包)之外。第三种情况(最后一个else
)只是为了演示。
工作示例:
(我省略了 navSlide()
函数)
"use strict";
var burger = document.querySelector('.burger');
var nav = document.querySelector('.nav_links');
window.addEventListener('click', function(e) {
if (e.target.classList.contains('burger')) {
nav.classList.toggle('nav_active');
console.log("Clicked on Burger");
}
else if (!nav.contains(e.target)) {
nav.classList.remove('nav_active');
console.log("Clicked outside Box");
}
else {
console.log("Clicked in Box");
}
});
.nav_home,
.nav_links,
.nav_buttons,
.nav_list {
display: inline-block;
vertical-align: middle;
}
.burger {
width: 2.4rem;
height: 2.4rem;
margin: auto 0;
cursor: pointer;
background: black;
}
.nav_list a:hover {
text-decoration: line-through !important;
}
.nav_links {
display: block;
z-index: 0;
position: absolute;
right: 0rem;
width: 80%;
margin-right: 0.1rem;
border-left: 0.1rem solid;
background: red;
}
.nav_item {
display: block;
}
.nav_list {
display: block;
a {
display: block;
}
span {
display: none;
}
}
.nav_links.nav_active {
display: inline-block;
background-color: green;
}
<header id="header">
<div class="header container">
<div class="nav_links">
<h5 class="nav_list">
<span class="noselect">⁄</span>
</h5>
<div class="nav_buttons">
<h5 class="theme-label"></h5>
<input class="themeSwitch" type="checkbox" id="switch" name="theme" />
<label class="toggle" for="switch"></label>
<label class="switch" for="switch"></label>
</div>
</div>
<div class="burger"></div>
</div>
</header>
如果您希望仅在菜单打开 (nav.classList.contains("nav_active")
) 时添加第二个事件侦听器,否则将其删除,则必须将其嵌套到第一个侦听器的处理程序(匿名函数)中。您必须将第二个处理程序定义为单独的函数(此处 checkClickLocation()
),因为 removeEventListener()
需要函数引用(此处 checkClickLocation
)作为参数来停止它。
工作示例:
"use strict";
var burger = document.querySelector('.burger');
var nav = document.querySelector('.nav_links');
function checkClickLocation(e) {
if (!nav.contains(e.target)) {
nav.classList.remove('nav_active');
window.removeEventListener('click', checkClickLocation);
console.log("Clicked outside Box");
}
else {
console.log("Clicked in Box");
}
}
burger.addEventListener('click', function(e) {
e.stopPropagation()
nav.classList.toggle('nav_active');
if (nav.classList.contains("nav_active")) {
window.addEventListener('click', checkClickLocation);
}
else {
window.removeEventListener('click', checkClickLocation);
}
console.log("Clicked on Burger");
});
.nav_home,
.nav_links,
.nav_buttons,
.nav_list {
display: inline-block;
vertical-align: middle;
}
.burger {
width: 2.4rem;
height: 2.4rem;
margin: auto 0;
cursor: pointer;
background: black;
}
.nav_list a:hover {
text-decoration: line-through !important;
}
.nav_links {
display: block;
z-index: 0;
position: absolute;
right: 0rem;
width: 80%;
margin-right: 0.1rem;
border-left: 0.1rem solid;
background: red;
}
.nav_item {
display: block;
}
.nav_list {
display: block;
a {
display: block;
}
span {
display: none;
}
}
.nav_active {
display: inline-block;
background-color: green;
}
<header id="header">
<div class="header container">
<div class="nav_links">
<h5 class="nav_list">
<span class="noselect">⁄</span>
</h5>
<div class="nav_buttons">
<h5 class="theme-label"></h5>
<input class="themeSwitch" type="checkbox" id="switch" name="theme" />
<label class="toggle" for="switch"></label>
<label class="switch" for="switch"></label>
</div>
</div>
<div class="burger"></div>
</div>
</header>