You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何等待Vue插槽内容渲染后判断组件是否可滚动?

Vue中等待插槽渲染完成后判断容器是否可滚动的解决方案

问题背景

开发BitBox组件时,需要判断外层容器#bit-box是否可滚动(通过scrollHeight > clientHeight判断)。容器内容通过Vue插槽传入,插槽数据页面加载初始即可获取无需AJAX,但在组件的onMounted钩子中调用isScrollable函数始终返回false,页面完全渲染后在控制台手动调用则返回true。

滚动判断函数:

export function isScrollable(ele){
    return ele.scrollHeight > ele.clientHeight;
}

BitBox组件核心代码:

const bitBox = shallowRef<HTMLDivElement>();

onMounted((): void => {
    if (typeof bitBox.value === 'undefined'){
        return;
    }

    // DOMContentLoaded此时已触发,不会执行
    document.addEventListener('DOMContentLoaded', function () {
        alert('WE ARE READY');
    });

    // 此时插槽内容未渲染完成,判断错误
    if(isScrollable(bitBox.value)){
        alert('Scrollable Yeeeah 1');
    } else {
        alert('Scrollable Naaah 1');
    }
});
<template>
    <div ref="bitBox" id="bit-box">
        <slot name="content"></slot>
    </div>
</template>

组件使用方式:

<template>
<BitBox>
    <template #content>
        <p v-for="someData in dataset" :key="someData.id">
            {{ someData.title }}
        </p>
    </template>
</BitBox>
</template>

原因分析

Vue的onMounted钩子触发时机是组件自身DOM挂载完成,但插槽内容(尤其是包含v-for的列表)属于父组件传递的内容,其渲染完成时机晚于子组件的onMounted。此时容器的scrollHeight还未更新为插槽内容渲染后的实际高度,导致isScrollable判断错误。

另外,DOMContentLoaded事件在页面初始HTML加载解析完成后就会触发,而onMounted是在组件挂载时执行,此时该事件早已触发,所以添加监听不会生效。

解决方案

方法1:使用nextTick等待DOM更新

nextTick会在Vue的DOM更新循环结束后执行回调,此时插槽内容已完成渲染,容器的scrollHeight已更新。

修改BitBox组件的onMounted逻辑:

const bitBox = shallowRef<HTMLDivElement>();

onMounted((): void => {
    if (!bitBox.value) return;

    nextTick(() => {
        if(isScrollable(bitBox.value)){
            alert('Scrollable Yeeeah');
        } else {
            alert('Scrollable Naaah');
        }
    });
});

方法2:监听插槽内容的变化(可选,适用于数据动态更新场景)

如果插槽内容依赖的数据可能动态更新,可通过监听数据变化,再结合nextTick重新判断:

在使用BitBox的父组件中:

const dataset = ref([/* 初始数据 */]);

watch(dataset, () => {
    nextTick(() => {
        const bitBoxEle = document.getElementById('bit-box');
        if (bitBoxEle && isScrollable(bitBoxEle)) {
            // 处理滚动逻辑
        }
    });
}, { deep: true });

方法3:使用MutationObserver监听容器变化

如果需要更精确地监听容器内容的DOM变化(比如插槽内容可能通过其他方式动态添加),可以使用MutationObserver:

在BitBox组件的onMounted中:

const bitBox = shallowRef<HTMLDivElement>();

onMounted((): void => {
    if (!bitBox.value) return;

    const observer = new MutationObserver(() => {
        if(isScrollable(bitBox.value)){
            alert('Scrollable Yeeeah');
            observer.disconnect(); // 判断完成后停止监听
        }
    });

    // 监听容器的子节点变化
    observer.observe(bitBox.value, {
        childList: true,
        subtree: true
    });
});

内容的提问来源于stack exchange,提问作者ii iml0sto1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 03:05:29