Javascript 将鼠标悬停在工具提示上方时,使v形工具提示保持打开状态

Javascript 将鼠标悬停在工具提示上方时,使v形工具提示保持打开状态,javascript,vue.js,vuetify.js,Javascript,Vue.js,Vuetify.js,首先,术语“链接”是鼠标进入的区域。“工具提示”是弹出并显示额外信息的东西。 ---以上添加于2020年4月29日 我正在使用Vuetify,并试图在鼠标悬停在“工具提示”上时保持v形工具提示打开。 工具提示中的内容将会很丰富,不希望在访问者查看时自动隐藏 <template> <v-tooltip v-model="show" max-width="600px" content-class="link-tooltip-content" bottom>

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

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

<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>

丰富的工具提示
导出默认值{
数据:()=>({
秀:假,,
悬停计时器:空
}),
方法:{
boxStyle:function(){
返回{
左:“100px”,
顶部:“100px”,
宽度:“100px”,
高度:“100px”,
位置:“绝对”
};
},
mouseover:function(){
log(`mouseover`);
this.show=true;
clearTimeout(这个.hoverTimer);
},
mouseleave:function(){
log(`mouseleave`);
this.hoverTimer=setTimeout(()=>{
this.show=false;
}, 3000);
}
}
};
但这不起作用。激活器插槽(“link”)元素上的mouseover和mouseleave事件处理程序会启动,但默认插槽(“工具提示”)上的事件处理程序不会启动

我认为原因是,因为“工具提示”中的内容被移动到body标记下的其他位置

问题是,当我将鼠标悬停在“工具提示”上时,如何使其保持打开状态

我像这样移动鼠标:

  • 将鼠标悬停在链接上(工具提示将显示)
  • 将鼠标移出链接并移到工具提示中。(链接和工具提示相隔几个像素) 现在,链接的mouseleave事件触发,我想在工具提示上添加一个mouseenter事件处理程序我该怎么做?
  • 我想在工具提示上添加一个mouseenter事件,这样我就可以
    clearTimeout(hoverTimer)
    并保持工具提示打开

    我知道9年前有一个类似的问题,使用jQuery,但如果可能的话,我不想使用jQuery。我更喜欢Vue方式

    这里有一个可重复的小例子:
    .v-tooltip\u内容
    具有
    指针事件:无
    设置在
    vuetify.min.css
    中。如果将其设置回
    auto
    ,则允许将其悬停

    当其父对象悬停时,其父对象悬停。当其父对象悬停时,它会有一个工具提示。因此,您所需要的是:

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

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

    例如:


    为此,我制作了VTooltip的扩展版本。只需通过
    interactive
    prop。将“创建者”悬停在列表项中,查看此处的工作示例:

    
    /**
    *使用交互性扩展VTooltip
    *@见https://material-ui.com/components/tooltips/#interactive
    */
    从“vuetify/lib”导入{VTooltip};
    导出默认值{
    扩展:VTooltip,
    道具:{
    交互式:{
    类型:布尔型,
    默认值:false,
    },
    关闭延迟:{
    类型:[数字,字符串],
    默认值:50,
    },
    },
    计算:{
    //我不是百分之百确定,但它是有效的
    计算左(){
    const originalValue=VTooltip.options.computed.calculatedLeft.call(this);
    如果(!this.interactive)返回originalValue;
    常数{left,right}=这个;
    let value=parseInt(原始值);
    如果(左| |右){
    值+=右?-10:10;
    }
    返回`${value}px`;
    },
    calculatedTop(){
    const originalValue=VTooltip.options.computed.calculatedTop.call(this);
    如果(!this.interactive)返回originalValue;
    const{top,bottom}=这个;
    let value=parseInt(原始值);
    如果(顶部| |底部){
    值+=底部?-10:10;
    }
    返回`${value}px`;
    },
    样式(){
    const originalValue=VTooltip.options.computed.styles.call(this);
    如果(!this.interactive)返回originalValue;
    常数{
    上,下,左,右,
    }=这个;
    让填充方向;
    如果(底部)填充方向=‘顶部’;
    否则,如果(顶部)填充方向=‘底部’;
    如果(右)填充方向为“左”,则为else;
    如果(左)填充方向为“右”,则为else;
    返回{
    …原始价值,
    [`padding-${paddingDirection}`]:`${10}px`,
    };
    },
    },
    方法:{
    ONTOOLTIMPOUSEENTER(e){
    if(this.interactive){
    这个.clearDelay();
    this.isActive=true;
    }
    此.emit('工具提示:mouseenter',e);
    },
    离港(东){
    if(this.interactive){
    这个.clearDelay();
    这是runDelay('close');
    }
    此.emit('工具提示:mouseleave',e);
    },
    genContent(){
    const content=this.$createElement('div',this.setBackgroundColor(this.color{
    style:this.contentStyles,
    staticClass:“v-工具提示内容”,
    类别:{
    [this.contentClass]:对,
    菜单内容活动:this.isActive,
    },
    }),this.getContentSlot());
    返回此.$createElement('div'{
    风格:这个。风格,
    attrs:this.getScopeIdAttrs(),
    类别:{
    “v-工具提示包装器”:true,
    “也是
    
        <v-menu open-on-hover right offset-x nudge-right="20" close-delay="100">
    
    <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>