vue 自定义指令实现popover气泡弹窗

效果展示
在这里插入图片描述

1 、写好 popover 组件
2、创建 自定义指令 popover.js 文件

<!--v-popover指令-->
<template>
    <div class="zdy-popover" ref="ref-zdy-popover" :class="[{'fade-in':visible}]" v-if="visible">
        <div class="zdy-popover-detail">
                <div  class="zdy-popover-detail-body">{{content}}</div>
                 <div class="triangle"></div>
        </div>
       
    </div>
</template>
<script>
export default {
    name: 'ZdyPopover',
    props: {
        visible: {
            type: Boolean,
            default: false
        },
        content:{
            type:String,
            default:''
        }
    }
};
</script>
<style lang="scss" scoped>
@keyframes fade-in {
  0% {
    opacity: 0;
  }
  30% {
    opacity: 0.3;
  }
  60% {
    opacity: 0.6;
  }

  100% {
    opacity: 1;
  }
}
.fade-in {
  animation: fade-in 200ms ease-out both 1 /*infinite*/;
}
.zdy-popover{
    position: absolute;
    z-index: 302;
    &-detail{
        padding: 8px 10px;
        background: rgba(34, 34, 34, 0.8);
        border-radius: 4px;
        position: relative;
        max-width: 180px;
         pointer-events: none; //防止穿透
        &-body{
            
            font-size: 12px;
            color: #FFFFFF;
            line-height: 20px;
            text-align: justify;
        }
        .triangle {
                            position: absolute;
                            display: block;
                            left: 10px;
                            top: -6px;
                            transform: translateY(-50%);
                            width: 0px;
                            height: 0px;
                            content: '';
                            border-color: transparent;
                            border-style: solid;
                            border-width:6px;
                            border-bottom:6px solid rgba(34, 34, 34, 0.8);
                            z-index: 220;
                        }
    }
    
}
</style>

popover.js

import Vue from 'vue';
import ZdyPopover from '@/components/common/qm-popover.vue';

const Popover = Vue.extend(ZdyPopover);
const _popover = {
    bind(el, binding, vnode) {
        const popper = new Popover({
            el: document.createElement('div'),
            data(){
                return {}
            }
        })
        document.body.style.position='relative'; // 将body 设置相对定位
        document.body.appendChild(popper.$el); //
        el.instance = popper;
        el.instance.content = binding.value.content || '';// 气泡中的文字
        // const _style={top:`${_offsetTop+_offsetHeight}px`, left:`${_offsetLeft}px`}
        el.onmouseenter=()=>{
            el.instance.visible=true; // 展示
            Vue.nextTick(()=>{
                const _top1 = el.getBoundingClientRect().top // 获取元素距离 顶部位置
                const _top2 = document.body.scrollTop||document.documentElement.scrollTop // 获取滚动 高度
                const _offsetTop =_top1+_top2+4; // 距离顶部高度  ui 4px 间距
                const _offsetLeft =el.getBoundingClientRect().left; // 距离右边 距离
                const _offsetHeight =el.offsetHeight; // 绑定元素高度
                const $popover =el.instance.$refs['ref-qm-popover'];
                $popover.style.top=`${_offsetTop+_offsetHeight}px`;
                $popover.style.left=`${_offsetLeft}px`;
            })
            
        }
        el.onmouseleave=()=>{
            el.instance.visible=false; // 展示
            // document.body.style.position='static'; // 将body static
            
        }
     
        
    },
    update() { },
    unbind(el, binding) {
    // 解除事件监听
        el.instance && el.instance.$destroy();
    }
};

export default _popover;
import popover from '@/directive/popover.js'
Vue.directive('popover', popover); //注册 全局 指令

调用方式 
<em v-popover="{content:'我是自定义指令气泡文案'}">demo</em>

在这里插入图片描述

Logo

前往低代码交流专区

更多推荐