繁体   English   中英

将鼠标悬停在工具提示上时保持 v-tooltip 打开

[英]Keep v-tooltip open when hovering over the tooltip

首先,术语,“链接”是鼠标进入的区域。 “工具提示”是弹出并显示额外信息的东西。 --- 以上添加于 2020-04-29

我正在使用 Vuetify 并试图在鼠标悬停在“工具提示”上时保持 v-tooltip 保持打开状态。 工具提示中的内容将会很丰富,并且不希望在访问者查看它时自动隐藏。

<template>
<v-tooltip
  v-model="show"
  max-width="600px"
  content-class="link-tooltip-content"
  bottom>
  <template v-slot:activator="{ on }">
    <div
      :style="boxStyle"
      @mouseover="mouseover"
      @mouseleave="mouseleave"
    ></div>
  </template>
  <template v-slot:default>
    <v-card
      @mouseover="mouseover"
      @mouseleave="mouseleave"
      >
      <v-row dense>
        <v-col>
          <v-card-title class="headline">
            rich tooltip
          </v-card-title>
        </v-col>
      </v-row>
    </v-card>
  </template>
</v-tooltip>
</template>

<script>
    export default {
  data: () => ({
    show: false,
    hoverTimer: null
  }),
  methods: {
    boxStyle: function() {
      return {
        left: "100px",
        top: "100px",
        width: "100px",
        height: "100px",
        position: "absolute"
      };
    },
    mouseover: function() {
      console.log(`mouseover`);
      this.show = true;
      clearTimeout(this.hoverTimer);
    },
    mouseleave: function() {
      console.log(`mouseleave`);
      this.hoverTimer = setTimeout(() => {
        this.show = false;
      }, 3000);
    }
  }
};
</script>

但这不起作用。 激活器槽(“链接”)元素上的 mouseover 和 mouseleave 事件处理程序会触发,但默认槽(“工具提示”)上的事件处理程序不会触发。

我认为原因是,因为“工具提示”内的内容被移动到了 body 标签下的其他地方。

问题是,当悬停在“工具提示”上时,如何保持打开状态。

我像这样移动鼠标:

  1. Hover 通过链接(显示工具提示)。
  2. 将鼠标移出链接并进入工具提示。 (链接和工具提示相距几个像素) 现在触发链接的 mouseleave 事件,我想在工具提示上添加一个 mouseenter 事件处理程序。 我怎么做?

我正在考虑在工具提示上添加一个 mouseenter 事件,以便我可以clearTimeout(hoverTimer)并保持工具提示打开。

我知道 9 年前有一个类似的问题,使用 jQuery 鼠标悬停时保持工具提示打开,但如果可能的话我不想使用 jQuery 。 我更喜欢 Vue 的方式。

这是一个可重复的小例子: https://www.codeply.com/p/GuFXqAAU8Y

我建议您使用v-menu并将open-on-hover道具设置为true ,而不是使用v-tooltip 如果您必须轻推您在菜单中放置的任何内容,请确保设置适当的close-delay值,以便菜单在用户到达之前不会关闭。

示例: https://codepen.io/stephane303/pen/WNwdNxY

    <v-menu open-on-hover right offset-x nudge-right="20" close-delay="100">

.v-tooltip__contentvuetify.min.css中设置了pointer-events:none 如果将其设置回auto ,则允许将其悬停。

当其悬停时,其父级悬停。 当它的父级悬停时,它有一个工具提示。 所以你只需要:

.v-tooltip__content {
  pointer-events: auto;
}

为此,我制作了 VTooltip 的扩展版本。 只需通过interactive道具。 通过将“创建者”悬停在列表项中查看工作示例: https://tzkt.io/KT1RJ6PbjHpwc3M5rw5s2Nbmefwbuwbdxton/tokens

<script>
/**
 * Extends VTooltip with interactivity
 * @see https://material-ui.com/components/tooltips/#interactive
 */

import { VTooltip } from 'vuetify/lib';

export default {
    extends: VTooltip,
    props: {
        interactive: {
            type: Boolean,
            default: false,
        },
        closeDelay: {
            type: [Number, String],
            default: 50,
        },
    },
    computed: {
        // I'm not 100% sure in this, but it works
        calculatedLeft() {
            const originalValue = VTooltip.options.computed.calculatedLeft.call(this);
            if (!this.interactive) return originalValue;
            const { left, right } = this;
            let value = parseInt(originalValue);
            if (left || right) {
                value += right ? -10 : 10;
            }
            return `${value}px`;
        },
        calculatedTop() {
            const originalValue = VTooltip.options.computed.calculatedTop.call(this);
            if (!this.interactive) return originalValue;
            const { top, bottom } = this;
            let value = parseInt(originalValue);
            if (top || bottom) {
                value += bottom ? -10 : 10;
            }
            return `${value}px`;
        },
        styles() {
            const originalValue = VTooltip.options.computed.styles.call(this);
            if (!this.interactive) return originalValue;
            const {
                top, bottom, left, right,
            } = this;
            let paddingDirection;
            if (bottom) paddingDirection = 'top';
            else if (top) paddingDirection = 'bottom';
            else if (right) paddingDirection = 'left';
            else if (left) paddingDirection = 'right';
            return {
                ...originalValue,
                [`padding-${paddingDirection}`]: `${10}px`,
            };
        },
    },
    methods: {
        onTooltipMouseenter(e) {
            if (this.interactive) {
                this.clearDelay();
                this.isActive = true;
            }
            this.$emit('tooltip:mouseenter', e);
        },
        onTooltipMouseleave(e) {
            if (this.interactive) {
                this.clearDelay();
                this.runDelay('close');
            }
            this.$emit('tooltip:mouseleave', e);
        },
        genContent() {
            const content = this.$createElement('div', this.setBackgroundColor(this.color, {
                style: this.contentStyles,
                staticClass: 'v-tooltip__content',
                class: {
                    [this.contentClass]: true,
                    menuable__content__active: this.isActive,
                },
            }), this.getContentSlot());
            return this.$createElement('div', {
                style: this.styles,
                attrs: this.getScopeIdAttrs(),
                class: {
                    'v-tooltip__wrapper': true,
                    'v-tooltip__wrapper--fixed': this.activatorFixed,
                },
                directives: [{
                    name: 'show',
                    value: this.isContentActive,
                }],
                on: {
                    mouseenter: this.onTooltipMouseenter,
                    mouseleave: this.onTooltipMouseleave,
                },
                ref: 'content',
            }, [content]);
        },
        genActivatorListeners() {
            const listeners = VTooltip.options.methods.genActivatorListeners.call(this);

            if (this.interactive) {
                if (listeners.mouseenter) {
                    listeners.mouseenter = (e) => {
                        this.getActivator(e);
                        this.clearDelay();
                        if (!this.isActive) {
                            this.runDelay('open');
                        }
                    };
                }
            }

            return listeners;
        },
    },

};
</script>

<style lang="scss">
.v-tooltip__wrapper {
    position: absolute;
    &--fixed {
        position: fixed;
    }
    .v-tooltip__content {
        position: static;
    }
}
</style>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM