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

dea*_*dob 6 javascript safari html5 dom ios

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

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

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

以下是加载窗口小部件的代码(在设置所有窗口小部件之后,将片段添加到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);
}
Run Code Online (Sandbox Code Playgroud)

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

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;
}
Run Code Online (Sandbox Code Playgroud)

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

任何想法是什么原因造成的,以及什么解决方法?

dea*_*dob 1

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