javascript Vue组件:在div内打开下拉菜单

gdrx4gfi  于 2023-01-01  发布在  Java
关注(0)|答案(4)|浏览(174)

我正在为我的项目构建一个下拉组件,但是当我添加的组件是一个响应表时,菜单在div中是打开的。
下面是我的代码:https://codesandbox.io/s/fast-pond-pto57t?file=%2Fsrc%2FApp.vue

我怎样才能使下拉菜单附加到身体和设置一个变换(x,y)

oipij1gg

oipij1gg1#

尝试使用position: fixed !important;

new Vue({
  el: "#demo",
  data() {
    return {
      showMenu: false,
    };
  },
})
.dropdown-menu {
  position: fixed !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
<div id="demo">
  <div class="table-responsive">
    <table class="table table-bordered">
      <thead>
        <tr>
          <th>#</th>
          <th>Name</th>
          <th>Action</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>1</td>
          <td>Joe Band</td>
          <td>
            <div class="dropdown">
              <button class="dropdown-toggle" @click="showMenu = !showMenu">
                Action
              </button>
              <ul class="dropdown-menu" :class="{ show: showMenu }">
                <li><a>Item 1</a></li>
                <li><a>Item 2</a></li>
                <li><a>Item 3</a></li>
              </ul>
            </div>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</div>
unhi4e5o

unhi4e5o2#

我发现现有的两个答案都很有价值,但都不完整:

  • TripleN's answer未正确定位下拉菜单
  • Nikola's answer不会将.dropdown-menu追加到<body>,因此只要.dropdown的祖先之一具有除none(规范参考)之外的任何有效transform值,它就会停止工作。

据我估计,正确的解决办法是双管齐下:
1.允许弹出器(由Bootstrap 5内部使用)正确定位下拉菜单(弹出器内容),
1.下拉菜单打开时,将弹出器内容附加到<body>
差不多就是这样!
在Bootstrap的早期版本中,这个任务非常简单,我花了几个小时阅读Bootstrap 5和Popper的文档和示例,试图找到一种方法来完成这个简单的任务:为弹出器内容指定目标container
如果有人知道如何在Bootstrap 5 * 中实现这一点,而不必自己干预DOM,我很乐意学习如何实现。
最后我放弃了,在Popper定位之后,我自己在DOM中移动了菜单:
Working demo.
更详细地说,该混合解决方案:

  • 我使用Nikola的想法给菜单position: fixed,所以Popper做了繁重的定位工作
  • 使用TripleN的思想,在Popper定位菜单后,将其附加到<body>。另外,在下拉菜单关闭后,我将菜单移回其在DOM中的原始位置。这可能没有必要,但对我来说很有意义。常识。

这个解决方案似乎在所有情况下都有效,包括在3d转换的祖先中。我已经在最新的Vue 2(2.7.10)和最新的Vue 3(3.2.40)中进行了测试。
Composition中的逻辑完全相同。
边注:也许我要求太高了,但是,与以前的版本相比,我发现Bootstrap 5很难使用,文档也很差,至少在这个时候是这样。
这应该是一个微不足道的任务。在下拉菜单的配置中指定container: 'body'。完成!
我有点失望。

zmeyuzjn

zmeyuzjn3#

拆分下拉菜单到其他组件,在mounted挂钩使用document.body.appendChild下拉菜单元素(this.$el)。我已经在this sandbox更新。
希望这能有所帮助!

u5rb5r59

u5rb5r594#

这听起来像是vue3的teleport组件的一个很好的用例,通过指定一个目标元素,您可以告诉Vue将该元素发送到目标元素。
例如:

<Teleport to='body'>... this content will be sent to the body</Teleport>

to属性可以是任何有效的选择器,甚至可以是指向另一个元素的ref
您也可以使用disabled属性以编程方式禁用远程传输。在这种情况下,组件的内容将保留在其最初放置的位置。
如果你没有使用VUE 3,你仍然可以很容易地敲出一个组件来模仿同样的行为。心灵传输对于模态这样的东西很棒,因为它允许你摆脱嵌套元素所强加的位置限制。
有关更多信息,请查看teleport组件的documentation

相关问题