Vuetify V-Menu在打开第三方库的表单点击事件后立即关闭



我正在尝试将细胞景观整合到vuetify SPA中。将图形渲染为 v-card 元素已经在工作。同样有效的是一个点击处理程序,在单击图表中的注释时使用 vue 路由器导航到不同的页面。但是当我用打开上下文菜单(v-menu)的命令替换路由器推送时,上下文菜单永远不会出现。我已经仔细检查了如果从 vue 页面中的不同位置触发,是否会出现相同的上下文菜单。

打开上下文菜单是使用 vue 中注册的简单布尔值实现的,该值绑定到 v 菜单的 v 模型。通过将值设置为 true,上下文菜单应打开。

但是,当从 cytoscape 单击处理程序中将该值设置为 true 时,这种情况永远不会发生。

代码部分复制自 vuetify 示例。

这是模板:

<template>
<v-container fluid>
<v-layout row justify-center align-center>
<v-flex xs10>
<v-card>
<v-toolbar>
<v-btn @click="contextMenuOpen=true">Show Contextmenu</v-btn>
</v-toolbar> 
<div ref="cytoscape" class="cytoscape" style="width: 100%; height: 80vh;" id="cytopane"></div>
</v-card>
</v-flex>
</v-layout>
<v-menu v-model="contextMenuOpen" :position-x="x" :position-y="y" absolute offset-y>
<v-list>
<v-list-tile @click="doSomething()">
<v-list-tile-title>Do Somethin</v-list-tile-title>
</v-list-tile>
<v-list-tile @click="doSomethingElse()">
<v-list-tile-title>Do Someting</v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>
</v-container>
</template>

和 js 部分:

. . .
data: function () {
return {
contextMenuOpen: false,
style: [
{
selector: 'node',
style: {
. . .
}
}, {
selector: 'edge',
style: {
. . .
}
}
],
layout: {
name: 'cose-bilkent'
}
}
},
methods: {
showContextMenu: function (x, y) {
let vs = this
this.contextMenuOpen = false
this.x = x
this.y = y
this.$nextTick(() => {
this.contextMenuOpen = true
})
},
renderView: function (data) {
let vs = this
cytoscape.use(coseBilkent)
let cy = cytoscape({
container: document.getElementById(this.$refs['cytoscape'].id),
elements: data,
style: this.style,
layout: this.layout
})
cy.on('click', 'node', function (evt) {
vs.showContextMenu(evt.originalEvent.clientX, evt.originalEvent.clientY)
})
},
},
mounted() {
. . . 
this.renderView()
}

通过单击我放入的用于测试的工具栏中的按钮,将出现上下文菜单。我觉得奇怪的是,如果布尔值"contextMenuOpen"绑定到菜单的 v 模型,并且将从点击处理程序设置为 true,则该值将立即设置回 false。如果我从 v 菜单中的 v 模型绑定中删除变量,该值将保持为真。

这是线程问题吗?我做错了什么?

更新:我准备了一个js-fiddle来重现我遇到的问题: https://jsfiddle.net/gofrm76/0tkjp3rs/63/

UPDATE2:通过在contextMenuOpen上创建一个监视并在此监视中设置断点,我能够使用堆栈跟踪至少跟踪问题的根源。事实上,菜单显示一毫秒,并且由于菜单中执行的外部单击处理程序而立即关闭。这通常会发生在上下文菜单出现并且我再次单击屏幕上的其他地方以再次关闭它时。在 cytoscape 点击事件的情况下,我显然错过了某种事件传播停止,因为单击节点会导致菜单打开并立即触发点击外部处理程序。

UPDATE3:我在 vuetify v-menu 上找到了一个配置选项,该选项禁用了通过单击上下文菜单外部的某个位置来关闭上下文菜单的功能。通过将另一个布尔变量绑定到最初为 false 的"单击时关闭",并在短暂延迟后设置为 true,我绕过了上面提到的第二个事件的处理,菜单保持打开状态。延迟后,单击时关闭将设置回默认的"true",用户可以通过单击菜单外部来关闭菜单。

所以对我来说,这是我现在可以使用的解决方案。它还表明,更新 2 中关于这两个事件的假设是正确的,它还表明原始帖子具有误导性/不正确:v-menu 按预期工作,但实际问题是有两个事件从"第三方库"/细胞景观发出。

这给我留下了一个问题:我怎样才能防止第二个事件?

尽管这个问题是不久前提出的,但我最近遇到了同样的问题,并希望帮助那些面临类似问题的人。 所以,我意识到带有绝对道具的 vuetify 菜单仅适用于@contextmenu,而不能按预期与@click一起使用。原因是菜单的工作方式是它检查菜单外部的单击以关闭菜单。因此,当您单击另一个按钮时,该按钮会发出一个事件,尝试打开菜单,但同时,检测到菜单外的单击,从而导致菜单立即关闭。上下文菜单不会出现此问题,因为未检测到单击。 因此,我处理此问题的方法是延迟单击时打开菜单,以便在检测到菜单外的单击时触发关闭事件后触发。设置超时将解决此问题。

更新 :

调试您的应用程序后,我发现该问题与vuetify有关,因为您的v-menu组件导致了它....在前一个组件上使用v-show后,我发现该组件具有以下样式:

min-width: 0px;
transform-origin: left top 0px;
z-index: 0;
display: none;

也。。。您的contextMenuOpen立即转换的原因是因为您有两个语句改变了同一方法的值(我注释了更改)

当我用普通的div替换v-menu时,一切正常,请检查它:

https://jsfiddle.net/jhuxwkec/

最新更新