我正在尝试重新解释我的问题,并将完成我所做的所有步骤,特别是在我失败的地方。我不是很了解JS,而是通过实践和社区的帮助来学习。
我偶然发现了this answer并意识到了这个好处。由于我不想使用jQuery,我开始在JS中重写它。
引用@zzzzBov的jQuery代码:
$('a').on('click', function () {
$(this.hash).toggleClass('active').focus();
});
$('div').on('focusout', function () {
$(this).removeClass('active');
});
我的JS代码:
var navToggle = document.getElementsByClassName('js-site-nav-btn--toggle')[0];
var navMenu = document.getElementsByClassName('js-site-nav')[0];
navToggle.addEventListener('click', function() {
this.focus();
navMenu.classList.toggle('js-site-nav--open');
});
navMenu.addEventListener('blur', function() {
this.classList.remove('js-site-nav--open');
}, true);
打开菜单有效,问题是它只会关闭'点击'如果在之前单击了一次聚焦元素(菜单),则在菜单外部:
var navToggle = document.getElementsByClassName('js-site-nav-btn--toggle')[0];
var navMenu = document.getElementsByClassName('js-site-nav')[0];
navToggle.addEventListener('click', function() {
this.focus();
navMenu.classList.toggle('js-site-nav--open');
});
navMenu.addEventListener('blur', function() {
this.classList.remove('js-site-nav--open');
}, true);

.c-site-nav {
color: black;
list-style-type: none;
padding-top: 20px;
position: fixed;
overflow: hidden;
top: 0;
right: -200px;
width: 200px;
height: 100%;
transition: right .6s cubic-bezier(0.190, 1.000, 0.220, 1.000);
opacity: .9;
background-color: green;
}
.js-site-nav--open {
right: 0;
}
.c-site-nav-btn:hover {
cursor: pointer;
background-color: red;
}
.c-site-nav-btn {
position: fixed;
top: 20px;
right: 20px;
border: 0;
outline: 0;
background-color: black;
position: fixed;
width: 40px;
height: 40px;
}
.c-site-nav-btn__line {
width: 20px;
height: 2px;
background-color: white;
display: block;
margin: 5px auto;
}

<button class="c-site-nav-btn js-site-nav-btn--toggle">
<span class="c-site-nav-btn__line"></span>
<span class="c-site-nav-btn__line"></span>
<span class="c-site-nav-btn__line"></span>
</button>
<nav class="c-site-nav js-site-nav" tabindex="-1" role="navigation">
<ul class="c-site-nav__menu">
<li>
<a class="c-site-nav__item js-site-nav__item" href="/">TOPMENU</a>
</li>
<li>SUBMENU
<ul>
<li>
<a class="c-site-nav__item js-site-nav__item" href="/">MENU</a>
</li>
<li>
<a class="c-site-nav__item js-site-nav__item" href="/">MENU</a>
</li>
<li>
<a class="c-site-nav__item js-site-nav__item" href="/">MENU</a>
</li>
</ul>
</li>
<li>
<a class="c-site-nav__item js-site-nav__item" href="/portfolio">TOPMENU</a>
</li>
</ul>
</nav>
&#13;
首先,对话框中的链接不可点击。尝试 单击它或选项卡将导致对话框关闭之前 互动发生。这是因为聚焦内部元素 在再次触发focusin事件之前触发焦点事件。
修复是在事件循环上对状态更改进行排队。这可以 通过对浏览器使用setImmediate(...)或setTimeout(...,0)来完成 不支持setImmediate。排队后,可以通过a取消 随后关注:
第二个问题是,当链接出现时,对话框不会关闭 再次按下。这是因为对话框失去焦点,触发了 关闭行为,然后链接单击触发对话框 重新打开。
与上一期相似,需要管理焦点状态。 鉴于状态变化已经排队,它只是一个 在对话框触发器上处理焦点事件的问题:
引用@zzzzBov的jQuery代码:
$('a').on('click', function () {
$(this.hash).toggleClass('active').focus();
});
$('div').on({
focusout: function () {
$(this).data('timer', setTimeout(function () {
$(this).removeClass('active');
}.bind(this), 0));
},
focusin: function () {
clearTimeout($(this).data('timer'));
}
});
$('a').on({
focusout: function () {
$(this.hash).data('timer', setTimeout(function () {
$(this.hash).removeClass('active');
}.bind(this), 0));
},
focusin: function () {
clearTimeout($(this.hash).data('timer'));
}
});
我的JS代码:
var navToggle = document.getElementsByClassName('js-site-nav-btn--toggle')[0];
var navMenu = document.getElementsByClassName('js-site-nav')[0];
var navLink = document.getElementsByClassName('js-site-nav__item')[0];
navToggle.addEventListener('click', function() {
this.focus();
navMenu.classList.toggle('js-site-nav--open');
});
navMenu.addEventListener('focus', function() {
this.blur(function() {
setTimeout(function() {
this.classList.remove('js-site-nav--open');
}.bind(this), 0);
});
this.focus(function() {
clearTimeout();
});
});
navLink.addEventListener('blur', function() {
navLink.blur(function() {
setTimeout(function() {
navMenu.classList.remove('js-site-nav--open');
}.bind(), 0);
});
navLink.focus(function() {
clearTimeout();
});
});
打开菜单仍然有效,但关闭点击外部停止工作,经过研究我认为模糊和焦点是正确的方法,但我想我错过了一些必要的东西。
var navToggle = document.getElementsByClassName('js-site-nav-btn--toggle')[0];
var navMenu = document.getElementsByClassName('js-site-nav')[0];
var navLink = document.getElementsByClassName('js-site-nav__item')[0];
navToggle.addEventListener('click', function() {
this.focus();
navMenu.classList.toggle('js-site-nav--open');
});
navMenu.addEventListener('focus', function() {
this.blur(function() {
setTimeout(function() {
this.classList.remove('js-site-nav--open');
}.bind(this), 0);
});
this.focus(function() {
clearTimeout();
});
});
navLink.addEventListener('blur', function() {
navLink.blur(function() {
setTimeout(function() {
navMenu.classList.remove('js-site-nav--open');
}.bind(), 0);
});
navLink.focus(function() {
clearTimeout();
});
});
&#13;
.c-site-nav {
color: black;
list-style-type: none;
padding-top: 20px;
position: fixed;
overflow: hidden;
top: 0;
right: -200px;
width: 200px;
height: 100%;
transition: right .6s cubic-bezier(0.190, 1.000, 0.220, 1.000);
opacity: .9;
background-color: green;
}
.js-site-nav--open {
right: 0;
}
.c-site-nav-btn:hover {
cursor: pointer;
background-color: red;
}
.c-site-nav-btn {
position: fixed;
top: 20px;
right: 20px;
border: 0;
outline: 0;
background-color: black;
position: fixed;
width: 40px;
height: 40px;
z-index:9999;
}
.c-site-nav-btn__line {
width: 20px;
height: 2px;
background-color: white;
display: block;
margin: 5px auto;
}
&#13;
<button class="c-site-nav-btn js-site-nav-btn--toggle">
<span class="c-site-nav-btn__line"></span>
<span class="c-site-nav-btn__line"></span>
<span class="c-site-nav-btn__line"></span>
</button>
<nav class="c-site-nav js-site-nav" tabindex="-1" role="navigation">
<ul class="c-site-nav__menu">
<li>
<a class="c-site-nav__item js-site-nav__item" href="/">TOPMENU</a>
</li>
<li>SUBMENU
<ul>
<li>
<a class="c-site-nav__item js-site-nav__item" href="/">MENU</a>
</li>
<li>
<a class="c-site-nav__item js-site-nav__item" href="/">MENU</a>
</li>
<li>
<a class="c-site-nav__item js-site-nav__item" href="/">MENU</a>
</li>
</ul>
</li>
<li>
<a class="c-site-nav__item js-site-nav__item" href="/portfolio">TOPMENU</a>
</li>
</ul>
</nav>
&#13;
我相信我还有很多东西需要学习,但我们将非常感谢帮助。非常感谢你们。
答案 0 :(得分:7)
您可以在显示后立即将焦点设置在navmenu
上。如果用户点击它之外,将触发blur
事件并删除菜单。由于点击链接也会触发blur
事件,因此当用户点击菜单内的任何位置时,我们必须将菜单保留在屏幕上。可以使用isMouseDown
标志来监控。
以下是问卷第1部分中提供的代码段的增强版。
var navToggle = document.getElementsByClassName('js-site-nav-btn--toggle')[0];
var navMenu = document.getElementsByClassName('js-site-nav')[0];
var isMouseDown = false;
navToggle.addEventListener('click', function() {
this.focus();
navMenu.classList.toggle('js-site-nav--open');
navMenu.focus();
});
navMenu.addEventListener('mousedown', function() {
isMouseDown = true;
});
navMenu.addEventListener('mouseup', function() {
isMouseDown = false;
});
navMenu.addEventListener('mouseleave', function() {
isMouseDown = false;
});
navMenu.addEventListener('blur', function() {
if (!isMouseDown) {
navMenu.classList.remove('js-site-nav--open');
}
}, true);
.c-site-nav {
color: black;
list-style-type: none;
padding-top: 20px;
position: fixed;
overflow: hidden;
top: 0;
right: -200px;
width: 200px;
height: 100%;
transition: right .6s cubic-bezier(0.190, 1.000, 0.220, 1.000);
opacity: .9;
background-color: green;
}
.js-site-nav--open {
right: 0;
}
.c-site-nav-btn:hover {
cursor: pointer;
background-color: red;
}
.c-site-nav-btn {
position: fixed;
top: 20px;
right: 20px;
border: 0;
outline: 0;
background-color: black;
position: fixed;
width: 40px;
height: 40px;
}
.c-site-nav-btn__line {
width: 20px;
height: 2px;
background-color: white;
display: block;
margin: 5px auto;
}
<button class="c-site-nav-btn js-site-nav-btn--toggle">
<span class="c-site-nav-btn__line"></span>
<span class="c-site-nav-btn__line"></span>
<span class="c-site-nav-btn__line"></span>
</button>
<nav class="c-site-nav js-site-nav" tabindex="-1" role="navigation">
<ul class="c-site-nav__menu">
<li>
<a class="c-site-nav__item js-site-nav__item" href="/">TOPMENU</a>
</li>
<li>SUBMENU
<ul>
<li>
<a class="c-site-nav__item js-site-nav__item" href="/">MENU</a>
</li>
<li>
<a class="c-site-nav__item js-site-nav__item" href="/">MENU</a>
</li>
<li>
<a class="c-site-nav__item js-site-nav__item" href="/">MENU</a>
</li>
</ul>
</li>
<li>
<a class="c-site-nav__item js-site-nav__item" href="/portfolio">TOPMENU</a>
</li>
</ul>
</nav>
答案 1 :(得分:3)
我最近遇到了同样的问题,并不像听起来那么棘手。你需要给你的触发器一个tabindex&#39; (为了使其可聚焦,0是好的)。给它一个点击&#39;像这样的事件处理程序......
document.getElementById('myTrigger').addEventListener('click', function(){this.focus(); this.classList.toggle('openClass');});
在哪里&#39; openClass&#39;是触发菜单的那个。然后(假设var myTrigger)......
myTrigger.addEventListener('blur', function(){ this.classList.remove('openClass');})
在此处,单击切换可打开和关闭打开的类,但它也会以幻灯片方式设置焦点。点击时,元素失去焦点,模糊&#39;事件触发并且处理程序删除了类......
答案 2 :(得分:1)
我采取了不同的方法。我使用toggleClass确定菜单是否打开。根据这个类名,我改变了你的css,这样只要将类'showMenu'添加到我们的html标签,菜单就会打开。
clickOutside方法中的代码检查您是否在给定的classNames外部点击(在这种情况下是.js-site-nav和.js-site-nav-btn - toggle)。如果您单击的元素不是具有给定类名的元素,则菜单将关闭。
对于此回复中的错误加价感到抱歉,我正在工作,所以当我在家时,我会尝试改进此消息。
以下是我使用的代码:
<强> HTML 强>
<div class="container">
<button class="c-site-nav-btn js-site-nav-btn--toggle">
<span class="c-site-nav-btn__line"></span>
<span class="c-site-nav-btn__line"></span>
<span class="c-site-nav-btn__line"></span>
</button>
<nav class="c-site-nav js-site-nav" tabindex="-1" role="navigation">
<ul class="c-site-nav__menu">
<li>
<a class="c-site-nav__item js-site-nav__item" href="/">TOPMENU</a>
</li>
<li>SUBMENU
<ul>
<li>
<a class="c-site-nav__item js-site-nav__item" href="/">MENU</a>
</li>
<li>
<a class="c-site-nav__item js-site-nav__item" href="/">MENU</a>
</li>
<li>
<a class="c-site-nav__item js-site-nav__item" href="/">MENU</a>
</li>
</ul>
</li>
<li>
<a class="c-site-nav__item js-site-nav__item" href="/portfolio">TOPMENU</a>
</li>
</ul>
</nav>
</div>
<强> CSS 强>
.c-site-nav {
color: black;
list-style-type: none;
padding-top: 20px;
position: fixed;
overflow: hidden;
top: 0;
right: -200px;
width: 200px;
height: 100%;
transition: right .6s cubic-bezier(0.190, 1.000, 0.220, 1.000);
opacity: .9;
background-color: green;
}
.showMenu .js-site-nav {
right: 0;
}
.c-site-nav-btn:hover {
cursor: pointer;
background-color: red;
}
.c-site-nav-btn {
position: fixed;
top: 20px;
right: 20px;
border: 0;
outline: 0;
background-color: black;
position: fixed;
width: 40px;
height: 40px;
z-index:9999;
}
.c-site-nav-btn__line {
width: 20px;
height: 2px;
background-color: white;
display: block;
margin: 5px auto;
}
.container
{
width: 100%;
height: 100%;
background: red;
}
<强>的JavaScript 强>
var $parent = $('html');
var toggleClass = 'showMenu';
var container = $(".js-site-nav, .js-site-nav-btn--toggle");
function init()
{
$('.js-site-nav-btn--toggle').on('click touchend', toggleMenu);
$(document).on('click touchend', clickOutside);
}
function toggleMenu()
{
$parent.toggleClass(toggleClass);
}
function clickOutside(e)
{
if (!container.is(e.target) // if the target of the click isn't the container...
&& container.has(e.target).length === 0
&& $parent.hasClass(toggleClass)) // ... nor a descendant of the container
{
$parent.removeClass(toggleClass);
}
}
init();