Apple iOS 浏览器随机不会呈现动态加载的 HTML 对象

2023-12-20

我们遇到的问题仅在 iOS 浏览器 (iOS 12.0) 上明显,我们的 SPA 应用程序使用 HTML 对象标签通过 JavaScript 将小部件(HTML/CSS/JS 文件)加载到页面上。

该问题是间歇性的,当页面加载时,某些小部件不会在屏幕上显示/渲染,但会加载到 DOM 中,并且可以在 Safari Web Inspector 中使用完整元素属性进行查看/突出显示。但对其用户来说是“不可见的”。如果页面上要加载 4 个小部件,其中 2 个通常不会显示,并且每次都不会显示不同的小部件,并且没有可检测到的模式,则大约 50% 的时间会出现此问题。

小部件 javascript 加载事件正常运行,并且控制台中没有错误。在 Safari Web Inspector 中,我们可以看到非渲染对象中的一些 HTML 元素在位置 0,0 处加载,但它们在 DOM 中的样式是正确的(左侧和顶部设置正确,显示:内联等)。

以下是加载小部件的代码(在设置所有小部件后,片段将添加到 DOM):

function loadWidget(myFrag, widgetName) {
    var widgetObj = document.createElement("object");
    widgetObj.data = "widgets/" + widgets[widgetName].type + ".html";        // location of widget
    widgetObj.className = "widget unselectable";
    widgetObj.id = widgetName;
    widgetObj.name = widgetName;
    myFrag.appendChild(widgetObj);                                        // build widgets onto fragment
    widgetObj.addEventListener("load", widgetLoaded, false);            // Run rest of widget initialisation after widget is in DOM
    widgetObj.addEventListener("error", badLoad, true);
}

以下是加载事件中的代码,用于在加载后配置小部件(我们解决了一个 Chrome 错误,该错误也会影响 Safari,其中每个加载的对象都会触发两次加载事件):

function widgetLoaded(e) {
    var loadObj = e.target;
    if (loadObj === null) {
        // CHROME BUG: Events fire multiple times and error out early if widget file is missing so not loaded (but this still fires), force timeout
        return;
    }

    var widgetName = loadObj.id;
    // CHROME BUG: Workaround here is to just set the style to absolute so that the event will fire a second time and exit, then second time around run the entire widgetLoaded
    if ((parent.g.isChrome || parent.g.isSafari) && !widgets[widgetName].loaded) {
        widgets[widgetName].loaded = true;                          // CHROME: WidgetLoaded will get run twice due to bug, exit early first time.
        loadObj.setAttribute("style", "position:absolute");         // Force a fake style to get it to fire again (without loading all the other stuff) and run through second time around
        return;
    }

    var defView = loadObj.contentDocument.defaultView;            // Pointer to functions/objects inside widget DOM

    loadObj.setAttribute("style", "position:absolute;overflow:scroll;left:" + myWidget.locX + "px;top:" + myWidget.locY + "px;z-index:" + zIndex);

    loadObj.width = myWidget.scaleX * defView.options.settings.iniWidth;            // Set the width and height of the widget <object> in dashboard DOM
    loadObj.height = myWidget.scaleY * defView.options.settings.iniHeight;
}

该代码在 Chrome (Mac/Windows)、IE 和 Safari (Mac) 中正确执行,但是在 iOS Safari 和 iOS Chrome 中出现随机不可见加载问题。

有什么想法导致此问题以及解决方法吗?


经过大量调查后,我们无法找到此问题的确切根源,并且相当确定这是一个 webkit 错误。然而,有一个可接受的解决方法,即用 iframe 标记替换对象标记,并且它看起来工作方式完全相同(用 .src 替换 .data),而且它不会出现 onload 处的 chrome bug事件被触发两次,因此 Chrome 现在可以更快地运行我们的应用程序。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Apple iOS 浏览器随机不会呈现动态加载的 HTML 对象 的相关文章