Alpine.js中Resize Observer无法更新数据的问题求助
Alpine.js中Resize Observer数据无法实时更新的解决方法
使用Resize Observer监听元素尺寸变化,尝试更新Alpine.js的dimensions数组并在页面展示,但数据仅初始化时显示一次,窗口调整尺寸时无法更新。
原代码
JavaScript
function app() { return { init() { var ro = new ResizeObserver((entries) => { for (let entry of entries) { console.log(entry); this.dimensions.push({ dim: `${(entry.contentRect.width / 16).toFixed(2)}rem` }); } }); ro.observe(this.$refs.box); ro.observe(document.documentElement); }, dimensions: [], display: [] }; }
HTML
<div class="color"></div> <div class="wrapper" x-data="app()"> <p class="dimension" x-text="dimensions[1].dim"></p> <div class="box"> <p class="dimension" x-text="dimensions[0].dim" x-ref="box"></p> <pre class="code">margin-inline: max(0px,((100% - 64rem) / 2))</pre> </div> </div>
问题原因
每次触发Resize Observer回调时,代码都往dimensions数组push新元素,但页面绑定的是固定索引(dimensions[0]、dimensions[1]),因此只会显示第一次push的元素,后续新增的元素不会被页面绑定的表达式读取到。
解决方案
不要通过push新增元素,而是直接替换数组对应索引的元素;或者更简洁地使用独立变量存储每个元素的尺寸,避免数组索引绑定的问题。
方案1:修改数组元素而非新增
function app() { return { init() { const ro = new ResizeObserver((entries) => { entries.forEach((entry, index) => { // 替换对应索引的元素,确保页面绑定的表达式能读取到最新值 this.dimensions[index] = { dim: `${(entry.contentRect.width / 16).toFixed(2)}rem` }; }); }); ro.observe(this.$refs.box); ro.observe(document.documentElement); }, // 初始化数组长度为2,对应两个监听元素 dimensions: [{}, {}], display: [] }; }
方案2:使用独立变量(推荐)
如果不需要保存历史尺寸数据,用独立变量存储更清晰:
function app() { return { boxDim: '', htmlDim: '', init() { const ro = new ResizeObserver((entries) => { entries.forEach(entry => { const remValue = `${(entry.contentRect.width / 16).toFixed(2)}rem`; // 根据目标元素区分赋值 if (entry.target === this.$refs.box) { this.boxDim = remValue; } else if (entry.target === document.documentElement) { this.htmlDim = remValue; } }); }); ro.observe(this.$refs.box); ro.observe(document.documentElement); } }; }
对应的HTML修改为:
<div class="color"></div> <div class="wrapper" x-data="app()"> <p class="dimension" x-text="htmlDim"></p> <div class="box"> <p class="dimension" x-text="boxDim" x-ref="box"></p> <pre class="code">margin-inline: max(0px,((100% - 64rem) / 2))</pre> </div> </div>
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

