amp-script触发元素click时报Cannot read properties of undefined错误求助
问题原因
- 异步逻辑执行顺序错误
getBoundingClientRectAsync()是异步Promise方法,你将坐标赋值逻辑放在了then回调中,但可视区域判断的代码写在then外部,执行判断时top/left/bottom/right变量还未完成赋值,初始值全为undefined,直接导致判断逻辑完全不符合预期。 - amp-script安全规则限制
amp-script出于安全考虑,非用户主动交互触发的回调(比如滚动事件回调)中不允许调用原生click()方法模拟用户点击,你在scroll回调中触发loadmore.click()本身就违反了amp-script的运行规则,这是报错的直接诱因。 - 变量作用域缺陷
坐标变量声明在全局作用域,多次触发scroll事件时会出现变量值互相覆盖的问题,进一步加剧逻辑混乱。
解决方法
核心修正点
- 把所有依赖坐标的逻辑全部放到
getBoundingClientRectAsync()的then回调内部,保证判断时已经拿到正确的坐标值 - 不要模拟按钮点击,把按钮触发的业务逻辑抽成公共函数,可视区域判断通过后直接调用函数即可,规避amp-script的交互限制
- 不要用全局变量存储坐标值,直接在回调内部使用局部变量即可
修正后代码示例
<amp-script script="btn-obs" layout="responsive" height="300" width="300" > <input class="load-more" id="btnloadmore" type="submit" value="TEST BTN" on="tap:formme.submit" tabindex="0" role="button"> </amp-script> <script id="btn-obs" type="text/plain" target="amp-script"> const loadmore = document.querySelector('#btnloadmore'); const targetForm = document.querySelector('#formme'); // 提前获取你要提交的表单元素 // 抽离公共逻辑,按钮点击和可视区触发都走这个函数 const handleLoadMore = () => { console.log("cliked"); targetForm.submit(); // 直接提交表单,不需要模拟按钮点击 } loadmore.addEventListener("click", handleLoadMore); window.addEventListener("scroll", function(event){ loadmore.getBoundingClientRectAsync().then(coords => { const { left, top, bottom, right } = coords; const viewHeight = window.innerHeight || document.documentElement.clientHeight; const viewWidth = window.innerWidth || document.documentElement.clientWidth; const isInViewport = top >= 0 && left >= 0 && bottom <= viewHeight && right <= viewWidth; if(isInViewport){ handleLoadMore(); console.log("yes") } }); }); </script>
额外优化建议
- 可以给scroll事件加防抖逻辑,减少高频触发带来的不必要计算
- 可以加一个已触发标记,避免按钮进入可视区后重复执行加载逻辑
内容的提问来源于stack exchange,提问作者imtrying
相关产品推荐
相关产品推荐

