Svelte代码刷新时随机返回不同高度值的原因是什么?
问题原因分析
你遇到的高度计算异常,核心原因是SMUI(Svelte Material UI)的组件样式为动态注入模式:
- 页面刷新时,DOM元素已经完成挂载,但SMUI的样式还在异步加载/解析中,此时
offsetHeight读取的是元素无样式(或部分样式未生效)状态下的高度(即你看到的25); - 热更新时,页面样式已经存在于浏览器缓存或已加载完成,组件渲染时样式立即生效,因此能得到正确的56px高度。
tick()仅能等待Svelte自身的DOM更新队列完成,无法处理第三方UI库的样式异步加载问题,所以没用。
解决方法
方法1:用requestAnimationFrame等待样式生效
利用浏览器的渲染帧机制,等待下一帧再测量,确保样式已应用:
<script lang='ts'> import { onMount } from 'svelte'; import DataTable, { Head, Row, Cell } from '@smui/data-table'; let headElement; let headHeight = 0; const measureHead = () => { if(headElement) { headHeight = headElement.offsetHeight; } } onMount(() => { // 等待下一渲染帧再执行测量 requestAnimationFrame(() => { measureHead(); console.log("Height: ", headElement.offsetHeight); }); }); </script> <DataTable table$aria-label="User list" style="width: 100%;" > <div bind:this={headElement}> <Head> <Row> <Cell style="width: 100%;">Title</Cell> <Cell>Type</Cell> <Cell numeric>Distance</Cell> </Row> </Head> </div> </DataTable>
方法2:用ResizeObserver监听高度变化
通过监听元素尺寸变化,在样式加载完成、高度更新时自动获取正确值:
<script lang='ts'> import { onMount, onDestroy } from 'svelte'; import DataTable, { Head, Row, Cell } from '@smui/data-table'; let headElement; let headHeight = 0; let resizeObserver; const measureHead = () => { if(headElement) { headHeight = headElement.offsetHeight; console.log("Height: ", headHeight); // 拿到正确高度后可停止监听,避免不必要的触发 resizeObserver?.unobserve(headElement); } } onMount(() => { resizeObserver = new ResizeObserver(measureHead); headElement && resizeObserver.observe(headElement); }); onDestroy(() => { // 组件销毁时清理观察者,防止内存泄漏 resizeObserver?.disconnect(); }); </script> <DataTable table$aria-label="User list" style="width: 100%;" > <div bind:this={headElement}> <Head> <Row> <Cell style="width: 100%;">Title</Cell> <Cell>Type</Cell> <Cell numeric>Distance</Cell> </Row> </Head> </div> </DataTable>
方法3:利用SMUI组件的初始化回调
查看SMUI的Head组件文档,若提供了类似onReady的props,可直接在组件完全初始化后触发测量,这是最精准的方式。
内容的提问来源于stack exchange,提问作者nick_jj
相关产品推荐
相关产品推荐

