Skip to content

Latest commit

 

History

History
98 lines (70 loc) · 2.34 KB

在单击位置显示自定义上下文菜单.md

File metadata and controls

98 lines (70 loc) · 2.34 KB

在单击位置显示自定义上下文菜单

当用户右键单击页面时,浏览器将显示默认上下文菜单。有时,我们希望用自己的菜单替换默认菜单,允许用户执行其他操作。

这篇文章演示了一个简单的实现。首先,让我们创建一个元素,以显示自定义的上下文菜单元素:

<div id="element">Right-click me</div>

<ul id="menu">...</menu>

防止显示默认上下文菜单

为了做到这一点,我们只需阻止 contextmenu 事件的默认操作:

const ele = document.getElementById('element')

ele.addEventListener('contextmenu', (e) => {
  e.preventDefault()
})

在单击的位置显示菜单

我们将计算菜单的位置,但首先需要绝对定位到其容器。因此,让我们将元素和菜单放置到位置 relative 的容器中:

<div class="relative">
  <div id="element">Right-click me</div>

  <ul id="menu" class="absolute hidden">...</menu>
</div>

relativeabsolutehidden 类定义如下:

.relative {
  position: relative;
}

.absolute {
  position: absolute;
}

.hidden {
  /* 菜单一开始是隐藏的 */
  display: none;
}

现在是设置菜单位置的时候了。可根据鼠标位置计算:

ele.addEventListener('contextmenu', (e) => {
  const rect = ele.getBoundingClientRect()
  const x = e.clientX - rect.left
  const y = e.clientY - rect.top

  // 设置菜单的位置
  menu.style.top = `${y}px`
  menu.style.left = `${x}px`

  // 显示菜单
  menu.classList.remove('hidden')
})

单击外部时关闭菜单

我们可以处理 documentclick 事件,并确定用户是否在菜单外单击:

ele.addEventListener('contextmenu', (e) => {
  // ...
  document.addEventListener('click', documentClickHandler)
})

// 在菜单外部单击时隐藏菜单
const documentClickHandler = (e) => {
  const isClickedOutside = !menu.contains(e.target)
  if (isClickedOutside) {
    // 隐藏菜单
    menu.classList.add('hidden')

    // 移除事件处理程序
    document.removeEventListener('click', documentClickHandler)
  }
}

通过添加 hidden 类可以隐藏菜单。

更重要的是,click 事件处理程序也从 document 中删除,因为当菜单隐藏时,我们不需要处理它。

查看效果