我们遇到的问题仅在 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 中出现随机不可见加载问题。
有什么想法导致此问题以及解决方法吗?