我正在尝试重新表述我的问题,并将完成我所做的所有步骤,特别是我失败的地方。我对 JS 的了解并不深,但有通过实践学习的意愿以及社区的帮助。
我偶然发现这个答案 https://stackoverflow.com/a/38317768/5597188并实现了好处。因为我不想使用 jQuery,所以我开始用 JS 重写它。
- 第一步是编写一个基本的简单函数,以在“单击”时打开菜单,并在使用模糊()在焦点元素外部单击时关闭菜单;方法。
参考 jQuery 代码@zzzzBov https://stackoverflow.com/a/38317768/5597188 :
$('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>
- 我尝试继续第二步,即解决两个主要问题:
首先是对话框中的链接不可单击。尝试
单击它或按 Tab 键将导致对话框在
发生交互作用。这是因为聚焦内部元素
在再次触发 focusin 事件之前触发 focusout 事件。
修复方法是在事件循环中对状态更改进行排队。这可以是
通过在浏览器中使用 setImmediate(...) 或 setTimeout(..., 0) 来完成
不支持 setImmediate。一旦排队,它可以被取消
后续重点:
第二个问题是链接打开时对话框不会关闭
再次按下。这是因为对话框失去焦点,触发
关闭行为,之后单击链接会触发对话框
重新打开。
与上一期类似,焦点状态需要管理。
鉴于状态更改已经排队,这只是一个
处理对话框触发器上的焦点事件的问题:
参考 jQuery 代码@zzzzBov https://stackoverflow.com/a/38317768/5597188 :
$('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();
});
});
.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;
}
<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>
我确信我还有很多东西需要学习,但非常感谢您的帮助。非常感谢大家。