根据element-plus tooltip组件源码而来。
之前网上搜了一下大多是增加元素再监听元素上点击事件

使用

<script>
import TriggerRef from "@/components/trigger-ref/index.vue";

const test = () => {
  console.log(222);
};
</script>

<template>
  <trigger-ref @click="test">
    <el-button>点击</el-button>
  </trigger-ref>
</template>

components/forward-ref/forward-ref.ts

import { Fragment, h, defineComponent } from "vue";

export default defineComponent({
  emits: ["init"],
  setup(props, { emit, slots }) {
    return () => {
      const setRef = (el: unknown) => {
        const elHTML = el ? (el as HTMLElement).nextElementSibling : null;

        if (elHTML) {
          emit("init", elHTML);
        }
      };

      const [firstChild] = slots.default?.() || [];

      if (!Array.isArray(firstChild.children) || firstChild.children.length > 1) {
        throw new Error("expect to receive a single Vue element child");
      }

      const child = firstChild.children[0];

      return h(
        Fragment,
        {
          ref: setRef
        },
        [child]
      );
    };
  }
});

components/forward-ref/index.vue

<script setup lang="ts">
import { onBeforeUnmount } from "vue";
import ForwardRef from "./forward-ref";

defineOptions({
  name: "TriggerRef"
});

const emit = defineEmits<{
  (event: "click"): void;
  (event: "hover"): void;
}>();

let slotElement: HTMLElement;

const events = {
  click: () => emit("click"),
  mouseenter: () => emit("hover")
};

/**
 * 初始化
 * @param el
 */
const refInit = (el: HTMLElement) => {
  slotElement = el;
  // 绑定事件
  Object.entries(events).forEach(([key, value]) => {
    slotElement.addEventListener(key, value);
  });
};

/**
 * 卸载移除事件
 */
onBeforeUnmount(() => {
  Object.entries(events).forEach(([key, value]) => {
    slotElement.removeEventListener(key, value);
  });
});
</script>

<template>
  <forward-ref @init="refInit"><slot /></forward-ref>
</template>

huzedong2015
10 声望1 粉丝