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.container
是 undefined
所以 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()
}
}
我有一个组件 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.container
是 undefined
所以 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()
}
}