在本教程中,我们将使用 vanilla javascript 创建一个可重用的自定义下拉组件。
一个什么?减少菜单或导航足迹的一种策略是在下拉组件中放置额外的链接。这个想法是用户单击以显示更多选项,从而为他们提供更多浏览网页的方式,同时保持 UI 清洁。
对于本教程,我假设我们正在为营销机构网站构建一个组件。
我们正在建设什么
这是我们灵活的下拉导航。单击带有箭头的项目以显示子菜单:
See the Pen Create a Custom Dropdown Component with JavaScript by Envato Tuts+ (@tutsplus) on CodePen.
如何使用 JavaScript 构建下拉组件
好吧,让我们陷入困境!像往常一样,我们将从结构的 html 标记开始,然后我们将使用 css 添加一些样式,最后我们将使用 vanilla javaScript 添加行为。
HTML结构
首先,HTML 结构。我们将使用带有列表项和链接的无序列表。
<nav role="primary navigation"> <a href="#">Home</a> <div class="dropdown"> <a href="#" class="dropdown-action"> services <svg class="dropdown-icon" xmlns="https://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><title>chevron-down</title><g fill="none"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M15.25 10.75L12 14.25l-3.25-3.5"></path></g></svg> </a> <ul class="dropdown-menu"> <li><a href="#">SEO</a></li> <li><a href="#">Content Strategy</a></li> <li><a href="#">Copywriting</a></li> <li><a href="#">Storytelling</a></li> </ul> </div> <a href="#">About</a> <a href="#">Contact</a> <div class="dropdown"> <a href="#" class="dropdown-action"> Account <svg class="dropdown-icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><title>chevron-down</title><g fill="none"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M15.25 10.75L12 14.25l-3.25-3.5"></path></g></svg> </a> <ul class="dropdown-menu"> <li><a href="#">Login</a></li> <li><a href="#">Sign up</a></li> </ul> </div> </nav>
.dropdown-action请注意父锚链接和无序列表上的类名.dropdown-menu。这些类命名约定更通用,因此我们可以在网站上随意重用 CSS 和 JavaScript。
使用 CSS 添加一些样式
让我们使用 CSS 对下拉列表进行一些美学处理。
请记住,下拉列表的核心基础是根据需要适当地隐藏和显示列表。我将考虑到这一点来设计下拉列表。
nav { width: 1020px; display: flex; align-items: center; margin: 20px auto; padding-bottom: 10px; border-bottom: 1px solid #ddd; } nav a { padding: 10px 16px; border-radius: 4px; display: inline-block; color: #334155; text-decoration: none; } nav a:hover { color: #0ea5e9; background-color: #f0f9ff; } .dropdown { position: relative; } .dropdown-action { display: flex; align-items: center; padding-right: 10px; } .dropdown-icon { stroke: currentColor; } .dropdown-menu { display: none; list-style: none; margin: 0; padding: 10px 0; border: 1px solid #cbd5e1; border-radius: 6px; box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); position: absolute; top: 40px; left: 5px; min-width: 180px; background: white; } .dropdown-menu.active { display: block; } .dropdown-menu a { display: block; }
使用 JavaScript 添加交互性
为了确保我们可以一遍又一遍地重用下拉组件,我将以一种方式编写 JavaScript,以考虑给定页面上的任何下拉组件。这意味着我们需要做的就是包含脚本以使其在许多下拉组件中工作,假设 HTML 和 CSS 与我们之前的工作相匹配。
class Dropdown { constructor() { this.dropdowns = document.queryselectorAll('.dropdown .dropdown-menu') if (this. dropdowns.length) { this.initialize(); } } initialize() { document.addeventListener('click', (e) => { if (e.target.classList.contains('dropdown-action')) { this.hideOtherDropdowns(e.target); this.handleClick(e.target); } else { this.hideOtherDropdowns(null); } }); } handleClick(dropdownAction) { this. dropdowns.forEach(dropdown => { if (dropdown.parentElement.contains(dropdownAction)) { dropdown.classList.add('active'); } else { dropdown.classList.remove('active'); } }) } hideOtherDropdowns(dropdownAction) { this.dropdowns.forEach((dropdown) => { if (!dropdown.parentElement.contains(dropdownAction)) { dropdown.classList.remove('active'); } }); } } document.addEventListener('domContentLoaded', () => new Dropdown);
使用现代 ES6 语法,我创建了一个新Dropdown类来包装逻辑以在给定页面上重用。我们使用以下行在最开始对其进行初始化。
document.addEventListener('DOMContentLoaded', () => new Dropdown);
只要脚本包含在给定页面中,此代码就是使组件活跃起来所需的全部内容。我们可以等待DOM 内容加载完成后再初始化Dropdown类以获得更好的结果。
我们的职能(更详细)
让我们分解每个功能并深入了解正在发生的事情。
构造方法
constructor() { this.dropdowns = document.querySelectorAll('.dropdown .dropdown-menu') if (this. dropdowns.length) { this.initialize(); } }
该constructor 方法用于初始化对象或类。构造函数使您能够在调用其他方法之前提供任何自定义初始化。
在这里,我添加了一个querySelectorAll查询给定页面上所有下拉菜单的方法。我们将在接下来的函数中遍历这些。
此外,我添加了一些条件逻辑来检查页面上是否存在下拉菜单,然后再调用initialize() 属于该类的函数。
初始化()函数
initialize() { document.addEventListener('click', (e) => { if (e.target.classList.contains('dropdown-action')) { this.hideOtherDropdowns(e.target); this.handleClick(e.target); } else { this.hideOtherDropdowns(null); } }); }
该initialize()函数调用类中的其他函数。这里我为整个 HTML 文档添加了一个事件监听器。当用户在给定下拉菜单之外单击时,我们需要这样做以响应用户的操作。一个好的体验是在菜单外点击时自动关闭菜单,所以这个逻辑说明了这一点。
我们可以通过使用返回的事件来利用“点击”,并利用它以供将来使用。这个想法是使用用户点击的项目为在页面上显示和隐藏正确的菜单铺平道路。如果有多个菜单,我们希望自动关闭不活跃使用的菜单。
如果导航菜单链接包含该类dropdown-action,我们将调用另外两个函数并将相同的目标值传递给它们。否则,我们将使用该函数关闭所有其他下拉菜单hideOtherDropdowns()。
handleClick() 函数
handleClick(dropdownAction) { this. dropdowns.forEach(dropdown => { if (dropdown.parentElement.contains(dropdownAction)) { dropdown.classList.add('active'); } else { dropdown.classList.remove('active'); } }) }
该handleClick()函数接受该event.target属性。我们从函数内部传递属性initialize()。我们将利用我们之前初始化的this.dropdowns数组来遍历所有存在的下拉列表。如果下拉菜单包含event.target(或dropdownAction),我们将类添加.active到下拉菜单并显示它。如果不是这种情况,我们将删除该类.active。
dropdownAction 参数
hideOtherDropdowns(dropdownAction) { this. dropdowns.forEach((dropdown) => { if (!dropdown.parentElement.contains(dropdownAction)) { dropdown.classList.remove('active'); } }); }
从长远来看,减少一次打开的下拉菜单会带来更好的体验。我们需要关闭任何未被积极使用的。我们可以找出相对于event.target 从函数中传递的对象而言使用的是哪个initialize()。dropdownAction这里我们为属性使用一个名为 sub in 的参数event.target 。
我们将再次遍历所有下拉菜单。在forEach循环中,我们可以执行一个条件语句来检查下拉列表是否包含dropdownAction。我们将使用 来!表示我们将检查逻辑的逆向。所以简单来说,我正在检查下拉列表是否不包含打开下拉列表的链接。如果不是,我们将删除它的活动类并隐藏它。
结论
运气好的话,您现在可以尝试打开和关闭我们在 HTML 中添加的两个下拉菜单,它们应该会按照我们的意愿进行响应。当一个打开时,另一个关闭。另请注意,当您在下拉菜单外单击时,原始下拉菜单也会关闭。
See the Pen Create a Custom Dropdown Component with JavaScript by Envato Tuts+ (@tutsplus) on CodePen.
- 我们正在建设什么
- HTML结构
- 使用 CSS 添加一些样式
- 使用 JavaScript 添加交互性
- 我们的职能(更详细)
- 构造方法
- 初始化()函数
- handleClick() 函数
- dropdownAction 参数
发表评论