如何在插槽上绑定事件而不破坏内容布局?

问题描述 投票:0回答:1

我试图制作一个基于插槽的上下文菜单组件,它应该像这样使用

<template>
<Contextmenu>
 <template #contextmenu>
  <!--customized contextmenu here-->
 <template>
 <template #default>
  <!--contents here-->
 <template>
<Contextmenu>
<template>

右键单击默认插槽时,会出现上下文菜单插槽,单击上下文菜单会发出事件。

组件内部就像这样

<template>
  <div class="contextmenu-wrapper" v-if="showContextMenu">
    <slot name="contextmenu"></slot>
  </div>
  <div class="content-wrapper" @contextmenu.prevent.stop="onRightclickContent">
    <slot name="default"></slot>
  </div>
</template>

div.contextmenu-wrapper
是固定的,
onRightclickContent
将设置它的
top
left
将其放在正确的位置。在安装的组件上,将注册一个事件侦听器,以在单击上下文菜单外部后关闭上下文菜单。

一切正常,但是当我尝试这个时:

<template>
  <div class="wrapper">
    <ContextMenu>
      <template #contextmenu>
        <div class="contextmenu"></div>
      </template>
      <div class="inner"></div>
      <div class="inner"></div>
      <div class="inner inner3"></div>
    </ContextMenu>
  </div>
</template>

<style>
.wrapper {
  display: flex;
  justify-content: space-evenly;
}

.inner {
  width: 250px;
  height: 100px;
  border: 1px solid #ccc;
  background-color: bisque;
}

.inner3 {
  flex-grow: 1;
}

.content {
  max-width: 100px;
  background-color: #3498db;
}
.contextmenu {
  width: 100px;
  height: 100px;
  background-color: azure;
}
</style>

问题是

div.content-wrapper
阻碍了弹性布局。但如果没有它,我如何监听内容上的右键单击事件?

解决方案是这样的:用 div 包裹整个组件,这样类就会落入它,然后将其布局在父组件中:

// ContextMenu.vue
<template>
<div class="wrapper" @contextmenu.prevent.stop="onRightclickContent">
  <div class="contextmenu-wrapper" v-if="showContextMenu">
    <slot name="contextmenu"></slot>
  </div>
  <slot name="default"></slot>
</div>
</template>

// parent component
<template>
  <div class="wrapper">
    <ContextMenu v-for="i in 3" class="inner">
      <template #contextmenu>
        <div class="contextmenu"></div>
      </template>
      <div class="content"></div>
    </ContextMenu>
  </div>
</template>

但是这样就会出现三个相同的右键菜单,内容比较杂乱,给用户带来麻烦。请帮我摆脱困境。

vue.js flexbox vue-component v-slot
1个回答
0
投票

问题解决了。

问题是,我不应该尝试影响父组件中的槽内容。因此,我没有在 slot#content 上绑定事件,同时保持其布局,而是让组件本身成为 Flex 容器:

// ContextMenu.vue
<template>
<div @contextmenu.prevent.stop="onRightclickContent">
  <div class="contextmenu-wrapper" v-if="showContextMenu">
    <slot name="contextmenu"></slot>
  </div>
  <slot name="default"></slot>
</div>
</template>

// parent component
<template>
  <!--no another wrapper div here!-->
    <ContextMenu class="wrapper">
      <template #contextmenu>
        <div class="contextmenu"></div>
      </template>
      <!--will be correctly layout now-->
      <div class="inner"></div>
      <div class="inner"></div>
      <div class="inner"></div>
    </ContextMenu>
</template>

<style>
.wrapper{
  display: flex;
}
</style>

class="wrapper"
将落入 ContextMenu 中的根 div,然后它成为 Flex 容器。

© www.soinside.com 2019 - 2024. All rights reserved.