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

Javascript 如何在Vue中检测组件内的元素是否溢出?,javascript,vue.js,dom,vue-component,overflow,Javascript,Vue.js,Dom,Vue Component,Overflow,我有一个组件ResultPill,带有主容器的工具提示(已实现)。工具提示文本由getter函数tooltip(我使用vue属性装饰器)计算,因此相关位为: <template> <div class="pill" v-vk-tooltip="{ title: tooltip, duration: 0, cls: 'some-custom-class uk-active' }" ref="container" >

我有一个组件
ResultPill
,带有主容器的工具提示(已实现)。工具提示文本由getter函数
tooltip
(我使用vue属性装饰器)计算,因此相关位为:

<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>
我发现对于我的组件
的许多实例,$refs.container
未定义的
,因此
isContainerSqueezed
实际上没有帮助。我是否必须为每个组件实例设置唯一的
ref
?这种方法还有其他问题吗?如何检查元素是否溢出

PS为了检查引用的非唯一性是否会影响案例,我尝试将以下内容添加到class a random id属性中:

        containerId = 'ref' + Math.random();
然后像这样使用它:

         :ref="containerId"
    >
    ....
            const container = this.$refs[this.containerId] as HTMLElement | undefined;
但它没有帮助:工具提示仍然没有改变

更好的是,还有
$el
属性,我可以用它来代替refs,但这仍然没有帮助。看起来原因是:

关于ref注册计时的一个重要注意事项:由于ref本身是作为render函数的结果创建的,因此您无法在初始渲染时访问它们-它们还不存在
$refs
也是非反应性的,因此不应尝试在模板中使用它进行数据绑定


(大概同样的情况也适用于
$el
),所以我不得不在挂载时重新添加
工具提示。看起来像我需要的,但答案不适用于我的情况。

因此,正如我在其中一次编辑中提到的,文档警告说,
$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()
    }
}

也许是打字稿的外壳?尝试直接调试
此.$refs.container
,除非您在装载之前设法调用该函数,否则应该始终定义它。@这是极不可能的,因为TS在生产中被剥离,所以
isContainerSqueezed
实际上只包含
const container=this.$refs.container
和比较。可能会影响这个案例的是整个decorator内容(它可能在没有TS的情况下使用)、vue中getter结果的一些“智能缓存”(DOM引用不可见,是吗?)或者对唯一引用的需要(不过我尝试将其切换为随机引用,但它不起作用;我将相应地更新这个问题)听起来仍然像是通话顺序的问题。尝试在
this.$nextTick(()=>{})中包装函数调用。在您的代码示例中,我看不出您在何时何地实际调用了
isContainerSqueezed()
函数。@Flame确实是(在上一次编辑中显示了
isContainerSqueezed
的用法;我使其更加详细和明显)。我最终使用了
挂载的
而不是
$nexTIck
,我将发布我目前使用的解决方案
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()
    }
}