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

Nuxt.js中如何执行DOM完全加载后运行的函数?

问题分析

核心问题在于SPA页面间导航时,表格列宽调整函数无法触发,仅刷新页面(SSR场景)时正常。原因是SSR模式下页面DOM在JavaScript执行前已完全构建,而SPA导航是客户端动态渲染DOM,onMounted+nextTick的时机可能赶不上表格DOM的实际渲染完成时间(比如表格依赖异步数据加载)。

解决方案

以下是针对性修复方案,按优先级排序:

方案1:监听表格数据变化(适用于异步加载表格数据的场景)

如果表格基于异步数据渲染,onMounted时数据可能未返回、表格DOM尚未生成,此时需监听数据加载完成后再执行列宽调整:

<script setup>
import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue';

// 假设表格数据为异步获取的变量
const tableData = ref([]);

const adjustTableColumnWidths = () => {
    const tables = document.querySelectorAll('.prose table');
    if (!tables.length) return; // 无表格时直接返回

    tables.forEach((table) => {
        const totalWidth = table.offsetWidth;
        const firstColWidth = totalWidth / 3;
        const colCount = table.rows[0]?.cells.length || 1;
        const otherColWidth = colCount > 1 ? (totalWidth - firstColWidth) / (colCount - 1) : totalWidth;

        Array.from(table.rows).forEach(row => {
            const firstCell = row.cells[0];
            if (firstCell) {
                firstCell.style.width = `${firstColWidth}px`;
            }

            for (let i = 1; i < row.cells.length; i++) {
                row.cells[i].style.width = `${otherColWidth}px`;
            }
        });
    });
};

// 监听表格数据变化,数据更新后执行调整
watch(tableData, async () => {
    await nextTick();
    adjustTableColumnWidths();
}, { deep: true });

onMounted(async () => {
    await nextTick();
    adjustTableColumnWidths();
    window.addEventListener('resize', adjustTableColumnWidths);
});

onUnmounted(() => {
    window.removeEventListener('resize', adjustTableColumnWidths);
});
</script>

方案2:利用路由切换事件(适用于页面级导航场景)

如果是Vue Router页面间导航,可在路由全局后置钩子中触发列宽调整,确保页面DOM完全渲染:
在router/index.js中添加:

import { nextTick } from 'vue';

router.afterEach(async () => {
    await nextTick();
    const adjustTableColumnWidths = () => {
        const tables = document.querySelectorAll('.prose table');
        if (!tables.length) return;
        
        tables.forEach((table) => {
            const totalWidth = table.offsetWidth;
            const firstColWidth = totalWidth / 3;
            const colCount = table.rows[0]?.cells.length || 1;
            const otherColWidth = colCount > 1 ? (totalWidth - firstColWidth) / (colCount - 1) : totalWidth;

            Array.from(table.rows).forEach(row => {
                const firstCell = row.cells[0];
                if (firstCell) {
                    firstCell.style.width = `${firstColWidth}px`;
                }

                for (let i = 1; i < row.cells.length; i++) {
                    row.cells[i].style.width = `${otherColWidth}px`;
                }
            });
        });
    };
    adjustTableColumnWidths();
});

若组件被keep-alive缓存,可在页面组件中使用onActivated钩子:

<script setup>
import { onActivated, nextTick } from 'vue';

// ... 其他代码

onActivated(async () => {
    await nextTick();
    adjustTableColumnWidths();
});
</script>

方案3:用MutationObserver监听DOM变化(通用兜底方案)

若不确定表格渲染时机,可监听.prose容器的DOM变化,当表格被添加时自动执行调整:

<script setup>
import { onMounted, onUnmounted, nextTick } from 'vue';

const adjustTableColumnWidths = () => {
    // 你的列宽调整函数逻辑
    const tables = document.querySelectorAll('.prose table');
    if (!tables.length) return;

    tables.forEach((table) => {
        const totalWidth = table.offsetWidth;
        const firstColWidth = totalWidth / 3;
        const colCount = table.rows[0]?.cells.length || 1;
        const otherColWidth = colCount > 1 ? (totalWidth - firstColWidth) / (colCount - 1) : totalWidth;

        Array.from(table.rows).forEach(row => {
            const firstCell = row.cells[0];
            if (firstCell) {
                firstCell.style.width = `${firstColWidth}px`;
            }

            for (let i = 1; i < row.cells.length; i++) {
                row.cells[i].style.width = `${otherColWidth}px`;
            }
        });
    });
};

let observer = null;

onMounted(async () => {
    await nextTick();
    adjustTableColumnWidths();
    window.addEventListener('resize', adjustTableColumnWidths);

    const proseContainer = document.querySelector('.prose');
    if (proseContainer) {
        observer = new MutationObserver((mutations) => {
            mutations.forEach(mutation => {
                if (mutation.addedNodes.length) {
                    const hasTable = Array.from(mutation.addedNodes).some(node => node.tagName === 'TABLE' || node.querySelector?.('table'));
                    if (hasTable) {
                        adjustTableColumnWidths();
                    }
                }
            });
        });

        observer.observe(proseContainer, {
            childList: true,
            subtree: true
        });
    }
});

onUnmounted(() => {
    window.removeEventListener('resize', adjustTableColumnWidths);
    if (observer) observer.disconnect();
});
</script>
关键优化点
  • 给函数添加空值判断,避免无效执行
  • 处理表格行/列数量异常的情况(比如仅一列的表格)
  • 根据实际场景选择匹配的触发时机,优先监听数据变化或路由事件,MutationObserver作为兜底

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 09:48:13