Android 的 Firefox onload 事件期间 window.innerWidth 的值错误?

Wrong value for window.innerWidth during onload event in Firefox for Android?

好的,所以,我面临的问题是:我的移动 Firefox 浏览器没有检索 window.innerWidthdocument.documentElement.clientWidth 甚至 [=15= 的宽度的正确值] 样式在页面加载后占据整个客户端 window。

我没疯,我的代码在所有其他浏览器中都运行良好!出于某种原因,Firefox 使用默认值初始化这些值,然后稍后获取正确的值。如果在任何时候我用 alert() 打断了我的 JavaScript,这些属性随后会神奇地变得准确。

我在互联网上搜索了一个答案,我所能找到的只是一个 hack 解决方法:使用 window.setTimeout 延迟这些属性的使用,直到它们有时间正确填充。这很疯狂!用户想要速度,而不是为了在 Firefox 浏览器上查看我的网站而额外延迟。

我不明白的是,我可以设置一个 div 来在值变得准确之前完美地填充客户端 window。我在 css 中通过将 div 的 id 的宽度和高度设置为 100% 来执行此操作。 document.documentElementdocument.getElementById("my_div"); 在所有文档元素加载后基本相同,因此,当浏览器没有正确的尺寸时,浏览器如何知道 div 应该有多大客户 window 第一?

我已经尝试 运行 我的代码在 window.addEventListener("load",function(event_){ //My Code }); 中,但仍然不会生成这些值。 window.onload 之后是否有页面加载事件?

如果有人能告诉我为什么只有 Firefox 移动版似乎显示出这种奇怪的行为,我会给你五分好评。

这里有一些用于重现问题的示例代码:

<!DOCTYPE HTML>
<html>
    <head>
        <!-- Added " after javascript during edit. -->
        <script type="text/javascript">
            window.addEventListener("load",function(event_){
                var output=document.getElementById("output");
                /* Returns some default value like 980. */
                output.innerHTML=window.innerWidth;

                alert("After this alert, the value will change.");
                /* Returns an accurate value like 511. */
                output.innerHTML=window.innerWidth;
            });
        </script>
        <!-- Added title during edit. -->
        <title>Title</title>
    </head>
    <body>
        <p id="output">Default Output</p>
    </body>
</html>

我的 Firefox android 版本是 35.0.1。我的 Android 版本是 4.4.4。在我的设备上,Firefox 在输出 p 元素中显示“980”,显示警报,然后再次显示“980”。页面刷新后,前两个步骤保持不变,但警报后的输出变为 360。document.documentElement.clientWidth 也会出现这种情况。我尝试的任何属性似乎都无法获得正确的值。似乎 Firefox 在页面加载后在访问客户端 window 的维度之前有某种延迟...

我在没有JQuery的情况下尝试了verge.airve.com插件,它的初始反馈仍然是980。它在Chrome上也初始化为980,这很奇怪,因为Chrome没有它按预期工作......

经过多次争论,找到了解决方案! Firefox 显然会在加载后调整 window 的大小(我想这是很好的衡量标准,谁知道呢)!因此,除了 window.onload 之外,还可以通过添加一个调整大小事件处理程序来避免这个问题!有关详细信息,请参阅下面接受的答案。

确保在加载整个文档并调整大小时完成测量。

window.onload = showViewport;
window.onresize = showViewport;

function showViewport() {
  var output=document.getElementById("output");
  var width = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
  var height= Math.max(document.documentElement.clientHeight, window.innerHeight || 0)
  output.innerHTML = "Viewport size is " + width + "x" + height;
}
<body>
  <p id="output">Default Output</p>
</body>

我可以确认这个问题,例如在 Android 4.1.2 上的 Firefox 38.0.1 中。创建了一个 js bin 用于测试目的。

我想检查 window.innerWidth 在不同分辨率(手机、平板电脑和台式机尺寸)上的自定义 DOM 操作,因此获得正确的 window.innerWidth 值已经处于 document.ready() 状态,而不仅仅是 window.load().

$('#inline').html($(window).width());

$(document).ready(function() {
  $('#ready').html(window.innerWidth);
});

$(window).load(function() {
  $('#load').html(window.innerWidth);
});

setTimeout(function() {
  $('#setTimeout').html(window.innerWidth);
}, 1000);
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>JS Bin</title>
</head>
<body>
  
  <p><span id="inline"></span></p>
  <p>$(document).ready(): <span id="ready"></span></p>
  <p>$(window).load(): <span id="load"></span></p>
  <p>setTimeout(1000): <span id="setTimeout"></span></p>
  
</body>
</html>

(我只想添加评论,而不是回答,但还没有这样做的声誉:-)

Firefox 40.0 在 Android 4.4.4 下的问题 (innerWidth === 980) 仍然存在。 1 毫秒的等待是一种规避。将

window.onload = myProgram; 
替换为

 window.onload = function() {setTimeout(myProgram, 1)};

同时,我在将一个相当精致的网站适配到小屏幕时遇到了这个问题。 Firefox 遵守“@media only screen and (max-width: 768px)”之后的 CSS。然而,当人们试图根据设备宽度设置事件处理程序时,Firefox 会惨遭失败。我需要在所有拾取设备宽度的位置等待 0.5 秒的上述技巧。这个等待时间对于 Nexus 7 (2012) 是必要的,但谁知道其他设备需要什么?

我在 CodeNameOne 和 Android

中使用 BrowserComponent 时遇到了同样的问题

我的解决方案是将 js 放在函数中,就像这样

function runScripts()
{
    //get width here
}

并监听 BrowserComponentonLoad 事件以在浏览器完全加载后执行此脚本

像这样:

    BrowserComponent browser = new BrowserComponent();
    browser.addWebEventListener("onLoad", new ActionListener() {

        public void actionPerformed(ActionEvent evt) {
            browser.execute("runScripts()");
        }
    });
    browser.setURL("http://www.URL.com");

在 html 中处理 window.onload 不足以等待提供适当的宽度

除此解决方案外,我还发现 window.setTimeout(runScripts, 500); 可以以浪费半秒为代价获得正确的文档宽度

window.setTimeout(yourFunction, 1);

这对我来说很有效,1 毫秒就足够了。

我发现一个非常 hack 的解决方案是在 header 中调用一个假的 link。我的猜测是时间延迟允许在脚本执行之前更新 window.innerWidth 和 window.innerHeight。

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/fake.css"/>

我遇到了同样的问题,在使用 Firefox 的 android 设备上获取 window.innerWidth 时宽度变了。我尝试了上面的一些建议,但没有成功 - 可能以错误的方式实施示例?

但是,通过使用下面的代码,据我测试,我得到的系统似乎 100% 正常工作。它也几乎没有延迟,因为它一旦获得稳定的结果就会打破循环。

var canvasWidth = 0;
var canvasHeight = 0;
    
var previousWidth = -1;
var previousHeight = -1;

while ((canvasWidth != previousWidth) || (canvasHeight != previousHeight))
{
  previousWidth  = canvasWidth;
  previousHeight = canvasHeight;
 
  canvasWidth  = window.innerWidth;
  canvasHeight = window.innerHeight;
}