自定义指令控制tooltip动态显示(vue3+elementplus案例)

940 阅读1分钟

 使用背景

平常我们再给文案过长时显示省略号,并且鼠标hover后通过tooltip显示完整文案。如果不做处理,会出现没有触发省略号时,鼠标hover后也会出现tooltip组件。因为此时的操作计算为dom宽度的计算,因此通过封装全局自定义指令统一实现。

具体实现

在utils文件夹新建trunced.ts文件,封装指令逻辑

// 控制tooltip触发时机指令
import type { ObjectDirective } from 'vue'

const syncVar = (node, binding, vnode) => {
  if (binding.arg) {
    binding.value[binding.arg] = node.offsetWidth < node.scrollWidth
  }
}

export const trunced: ObjectDirective = {
  mounted(el: HTMLButtonElement, binding, vnode) {
    syncVar(el, binding, vnode)
    const ro = new ResizeObserver((entries) => {
      entries[0].target && syncVar(el, binding, vnode)
    })
    ro.observe(el)
  },
  updated: function (el, binding, vnode) {
    syncVar(el, binding, vnode)
  },
}

在自定义指令文件夹/**/directives/index.ts文件夹下引入自定义指令

import { App } from 'vue'
// import setupPinia from './pinia'
// import setupCustomComponents from './globalComponents'
// import setupAssets from './resources'
// import setupDayjs from './dayjs'
// import setupMethods from './globalMethods'
import { setupDirectives } from './directives/index'

export function setupPlugins(app: App) {
  // setupAssets()
  // setupMethods(app)
  // setupPinia(app)
  // setupCustomComponents(app)
  // setupDayjs()
  setupDirectives(app)
}

注册指令

import { App } from 'vue'
// import setupPinia from './pinia'
// import setupCustomComponents from './globalComponents'
// import setupAssets from './resources'
// import setupDayjs from './dayjs'
// import setupMethods from './globalMethods'
import { setupDirectives } from './directives/index'

export function setupPlugins(app: App) {
  // setupAssets()
  // setupMethods(app)
  // setupPinia(app)
  // setupCustomComponents(app)
  // setupDayjs()
  setupDirectives(app)
}

组件内使用方式

  1. 给需要使用tootip的dom定义响应式变量
  2. 给dom定义出现省略号的固定样式
  3. 绑定自定义指令
<script setup lang="ts">
 const obj = reactive({
  sl: false,
  value: '11111111',
})
  
</script>
<template>
  <div class="container">
    <el-tooltip :disabled="!obj.sl" :content="obj.value">
      <div v-trunced:sl="obj" class="test">
        {{ value }}
      </div>
    </el-tooltip>
        <!-- 测试使用 -->
    <input v-model="value" />
  </div>
</template>

<style scoped lang="scss">
  .test {
    margin: 50px 0;
    background-color: red;
    color: #fff;
    width: 15%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
</style>