Vue如何检测组件内部的元素是否溢出?

How to detect whether an element inside a component is overflown in Vue?

我有一个组件 ResultPill,主容器带有工具提示(已实现 via vuikit)。工具提示文本由 getter 函数 tooltip 计算(我使用 vue-属性-decorator)所以相关位是:

<template>
    <div class="pill"
         v-vk-tooltip="{ title: tooltip, duration: 0, cls: 'some-custom-class uk-active' }"
         ref="container"
    >
        ..some content goes here..
    </div>
</template>
<script lang="ts">
    @Component({ props: ... })
    export default class ResultPill extends Vue {
    ...
        get tooltip (): string { ..calcing tooltip here.. }
        isContainerSqueezed (): boolean {
            const container = this.$refs.container as HTMLElement | undefined;
            if(!container) return false;
            return container.scrollWidth != container.clientWidth;
        }
    ...
</script>
<style lang="stylus" scoped>
    .pill
        white-space pre
        overflow hidden
        text-overflow ellipsis
    ...
</style>

现在,当组件被容器的宽度挤压并因此应用溢出样式时,我正在尝试向工具提示添加一些内容。使用控制台,我可以使用 [=16=].scrollWidth == [=16=].clientWidth(其中 [=17=] 是所选元素)粗略地检查它,但是当我使用

开始 tooltip 实现时
        get tooltip (): string {
            if(this.isContainerSqueezed())
                return 'aha!'

我发现对于我的组件的许多实例 this.$refs.containerundefined 所以 isContainerSqueezed 并没有真正帮助。我是否必须以某种方式为每个组件实例设置唯一的 ref ?这种方法还有其他问题吗?如何判断元素是否溢出?

PS 检查 refs 的非唯一性是否会影响案例,我尝试向 class 添加一个随机 ID 属性:

        containerId = 'ref' + Math.random();

并像这样使用它:

         :ref="containerId"
    >
    ....
            const container = this.$refs[this.containerId] as HTMLElement | undefined;

但这没有帮助:工具提示仍然没有改变。

更好的是,我可以使用 $el 属性 代替 refs,但这仍然无济于事。看起来原因是 this:

An important note about the ref registration timing: because the refs themselves are created as a result of the render function, you cannot access them on the initial render - they don’t exist yet! $refs is also non-reactive, therefore you should not attempt to use it in templates for data-binding.

(大概同样适用于 $el)所以我必须以某种方式重新计算挂载时的 tooltip 看起来像我需要的,但答案不适用于我的情况。

因此,就像我在其中一项编辑中提到的那样,文档警告说 $refs 不应该用于初始渲染,因为它们当时没有定义。因此,我将 tooltip 设为 属性 而不是 getter 并在 mounted:

中进行计算
export default class ResultPill extends Vue {
...
    tooltip = '';
    calcTooltip () {
        // specific logic here is not important, the important bit is this.isContainerSqueezed()
        // works correctly at this point
        this.tooltip = !this.isContainerSqueezed() ? this.mainTooltip :
            this.label + (this.mainTooltip ? '\n\n' + this.mainTooltip : '');
    }
    get mainTooltip (): string { ..previously used calculation.. }
    ...
    mounted () {
        this.calcTooltip()
    }
}