哇,这很难调试吗?似乎调试器缺少一些功能,例如跟踪事件的发射器。
问题在于 WooCommerce。具体来说,WooCommerce 似乎在 billing_last_name 输入字段上设置了 autofocus。然后浏览器会自动滚动页面以显示该字段。
人们希望有一个关闭自动对焦的配置选项,但似乎 WooCommerce 不提供此功能。
您可以尝试将其添加到您的主题中
function disable_autofocus_firstname($fields) {
$fields['billing']['billing_first_name']['autofocus'] = false;
return $fields;
}
add_filter('woocommerce_checkout_fields', 'disable_autofocus_firstname');
如果这不起作用,您可以创建一个 CSS 规则来隐藏帐单名称字段,然后在页面完全加载后运行延迟的 JS 函数来显示帐单名称字段。
我是如何调试它的
根据 OP 的要求,并考虑到提供的赏金,我将描述我是如何调试的。
我有点尴尬,我不只是对自己说“嗯,页面向上滚动到一个表单,光标在表单的第一个字段,我想知道它是否设置了自动对焦。”不幸的是,我主要不是前端程序员,一开始并没有想到autofocus。
我的想法是,它是通过 JavaScript 滚动的,要么是显式调用滚动函数,要么是通过在某些东西上设置 scrollTop。我在scroll 事件上放置了一个事件断点,并试图确定滚动事件的生成位置。虽然我找到了滚动事件,但我没有找到它的来源。在这个阶段我所能确定的是滚动事件的目标是document,而不是它里面的东西。
我使用monitorEvents 监听document 上的事件,发现只有 3 个,一个单击和 2 个滚动,最后一个是由 OP 插入的延迟滚动到顶部功能引起的,以解决第一卷。我在设置超时(不执行函数)时设置了一个执行断点,以尝试“分而治之”,即查看滚动是在此之前还是之后发生的。我在余下的调试工作中维护了该断点。
奇怪的是,通常页面在到达断点之前不会滚动,但有时会滚动。我觉得这很奇怪,虽然我不知道该怎么做,但它让我一直在寻找不寻常的东西。
我尝试在所有 JavaScript 中搜索“滚动”和“更新”(文本)以寻找更多要设置的断点,并在 JavaScript 上设置了一堆滚动,但没有命中。
我注意到有很多 JavaScript 动态更新页面,并认为滚动可能是由于某种更新。
我尝试在document 上放置一个jQuery event listener that logged all events(因为JS 使用了monitorEvents 未记录的自定义事件,并且我已经确定document 是scroll 事件的目标)发出所有事件,看看它是否是一些自定义更新事件。有一堆自定义事件,后来我在控制台中生成了这些事件,以查看页面是否会滚动响应。由于我无法让页面以这种方式滚动,因此我得出结论认为事件可能是死胡同。
我改变了战术。我查看了页面滚动到的位置,发现它正在将 WooCommerce 表单滚动到位。因此,在执行断点处停止时(如上所述),我从 DOM 中删除了整个 WooCommerce 表单,并验证页面不再滚动。这让我确信无论问题是什么,它都是由 WooCommerce 引起的。
很遗憾,我的 Google Fu 失败了,我没有立即通过 Google 搜索找到问题所在。相反,我发现 WooCommerce 如何滚动错误页面以确保错误消息可见。这让我回到了 JavaScript。
仍然有很多 JavaScript,其中很多是动态创建表单(即时本地化),还有一堆德语(我不会说),但我没有找到任何 JavaScript导致滚动。我真的很想缩小导致滚动的 JS 文件的范围。
Chrome 允许您在“脚本第一个语句”(在事件侦听器断点 -> 脚本下)设置断点,所以我这样做了。除了停在每个脚本文件的第一行之外,它还会停在页面上每个 <script> 标记的开头。我在页面底部附近找到了这个脚本标签
<script type="text/javascript">
if(typeof jQuery == 'undefined' || typeof jQuery.fn.on == 'undefined') {
document.write('<script src="https://www.prored3.de/wp-includes/js/jquery/jquery.js"><\/script>');
document.write('<script src="https://www.prored3.de/wp-includes/js/jquery/jquery-migrate.min.js"><\/script>');
}
</script>
这个脚本标签的奇怪之处在于,滚动是在这个脚本标签被处理之后立即发生的,但是 jQuery 已经加载了,所以脚本实际上什么也没做。我还能够通过控制台确认在此脚本标记之前和之后(即滚动之前和之后),DOM 未标记为 ready。这意味着在滚动发生时所有 jQuery ready 处理程序都没有运行。这消除了很多 JavaScript,让我思考为什么滚动发生在这个标签之后而不是之前。
我猜在内部,浏览器看到 document.write 调用并确定 DOM 直到它通过该标记后才完成,但是一旦它通过它,DOM 就完成了,它可以开始处理页面级属性。这与之前的观察一起,使我更仔细地查看了 WooCommerce 表单,并发现了在 billing_first_name 字段上设置的 autofocus 属性。
奇怪的是,我无法通过删除autofocus 属性来阻止滚动。我不知道为什么,但我猜这与浏览器内部以及 DOM 不是 ready 的事实有关。但是,我能够通过 CSS 将 billing_first_name 隐藏在 put 元素中来防止滚动,这让我确信这是滚动的原因。
在我的 Google 搜索中添加“自动对焦”让我收到了其他关于 WooCommerce 类似行为的投诉,合并帖子让我找到了我发布的 PHP 解决方案。