重新加载页面时未在 Safari 上触发加载事件
Load event not fired on Safari when reloading page
我在object
标签中加载了一个简单的SVG,如下代码所示。在 Safari 上,load
事件仅在打开浏览器后第一次加载页面时触发一次。所有其他时候它都没有。我正在使用 load
事件使用 GSAP 初始化一些动画,因此我需要知道 SVG 何时完全加载,然后才能选择 DOM 节点。似乎有效的快速解决方法是使用 setTimeout
而不是附加到事件,但这似乎有点奇怪,因为较慢的网络无法在指定的时间内加载object
。我知道这个事件并不是真正标准化的,但我不认为我是第一个遇到这个问题的人。你会如何解决它?
var myElement = document.getElementById('my-element').getElementsByTagName('object')[0];
myElement.addEventListener('load', function () {
var svgDocument = this.contentDocument;
var myNode = svgDocument.getElementById('my-node');
...
}
听起来更像是问题在于,当缓存数据时,加载事件会在您附加处理程序之前触发。
您可以尝试在附加事件后重置数据属性:
object.addEventListener('load', onload_handler);
// reset the data attribte so the load event fires again if it was cached
object.data = object.data;
我在开发Electron应用程序时也遇到了这个问题。在我的工作流程中,我在 VSCode 中编辑index.html
和renderer.js
,然后点击<Ctrl>+R
以查看更改。我只重新启动调试器来捕获对main.js
文件所做的更改。
我想加载一个 SVG,然后我可以从我的应用程序中操作它。因为SVG很大,我更喜欢把它保存在从磁盘加载的外部文件中。为此,HTML 文件index.html
包含以下声明:
<object id="svgObj" type="image/svg+xml" data="images/file.svg"></object>
renderer.js
中的应用程序逻辑包含:
let svgDOM // global to access SVG DOM from other functions
const svgObj = document.getElementById('svgObj')
svgObj.onload = function () {
svgDOM = this.contentDocument
mySvgReady(this)
}
该问题并不明显,因为它显示为间歇性:当调试器/应用程序首次启动时,这工作正常。但是当通过 <Ctrl>+R
重新加载应用程序时,.contentDocument
属性null
。
经过大量调查和拉扯,关于这一点的一些长篇笔记包括:
- 使用
svgObj.addEventListener ('load', function() {...})
而不是svgObj.onload
没有区别。使用addEventListener
更好,因为尝试通过"onload"设置另一个处理程序将替换当前处理程序。与其他Node.js
相反应用程序,你不需要removeEventListener
时元素旧版本的IE(11之前(有问题,但是这现在应该被认为是安全的(无论如何都不适用于Electron(。 - 最好使用
this.contentDocument
。有一个更好看的getSVGDocument()
有效的方法,但这似乎是针对反向的与旧的Adobe工具兼容,也许是Flash。返回的 DOM 是相同的。
SVG DOM 似乎在加载后被永久缓存,如@Kaiido所述,除了我相信该事件永远不会触发。更重要的是,在Node.js
中,SVG DOM仍然缓存在它被加载到的同一个svgDOM
变量中。我完全不明白这一点。我的直觉表明,index.html
中的require('renderer.js')
代码已将其缓存在模块系统中的某个地方,但对渲染器的更改确实会生效.js因此这不可能是全部答案。
无论如何,这里有一种在Electron的渲染过程中捕获SVG DOM的替代方法,它对我有用:
let svgDOM // global to access from other functions
const svgObj = document.getElementById('svgObj')
svgObj.onload = function () {
if (svgDOM) return mySvgReady(this) // Done: it already loaded, somehow
if (!this.contentDocument) { // Event fired before DOM loaded
const oldDataUri = svgObj.data // Save the original "data" attribute
svgObj.data = '' // Force it to a different "data" value
// setImmediate() is too quick and this handler can get called many
// times as the data value bounces between '' and the actual SVG data.
// 50ms was chosen and seemed to work, and no other values were tested.
setTimeout (x => svgObj.data = oldDataUri, 50)
return;
}
svgDOM = this.contentDocument
mySvgReady(this)
}
接下来,我非常失望地得知index.html
加载的CSS规则无法访问SVG DOM中的元素。有许多方法可以通过编程方式将样式表注入 SVG DOM 中,但我最终将index.html
更改为这种格式:
<svg id="svgObj" class="svgLoader" src="images/file.svg"></svg>
然后,我将这段代码添加到我的 DOM 设置代码中,以renderer.js
将 SVG 直接加载到文档中。如果您使用的是压缩的 SVG 格式,我希望您需要自己进行解压缩。
const fs = require ('fs') // This is Electron/Node. Browsers need XHR, etc.
document.addEventListener('DOMContentLoaded', function() {
...
document.querySelectorAll ('svg.svgLoader').forEach (el => {
const src = el.getAttribute ('src')
if (!src) throw "SVGLoader Element missing src"
const svgSrc = fs.readFileSync (src)
el.innerHTML = svgSrc
})
...
})
我不一定喜欢它,但这是我要采用的解决方案,因为我现在可以更改 SVG 对象上的类,并且我的 CSS 规则适用于 SVG 中的元素。例如,index.css
中的这些规则现在可用于以声明方式更改显示 SVG 的哪些部分:
...
#svgObj.cssClassBad #groupBad,
#svgObj.cssClassGood #groupGood {
visibility: visible;
}
...
- 无法在Safari中加载跨源映像(来自CloudFront)
- JQuery不会在Safari以外的任何浏览器中加载
- 在safari和chrome中,js图像加载产生了奇怪的结果
- 异步加载的SVG过滤器feColorMatrix在Chrome中工作,而不是在Safari或Firefox中
- window.location.hash = “”;强制在Chrome和Safari上重新加载框架集
- .submit JS函数在Safari中不显示CSS覆盖(除非我取消页面加载)
- XMLHttpRequest”;未能加载资源“;使用Safari
- 忽略Safari's初始页面加载popstate
- Mobile Safari在加载JS文件时挂起
- 如何在 JavaScript 中加载 Image(),而无需在 Safari 上缓存它
- 加载PDF文件/网址在Safari浏览器中显示黑屏
- 如何在加载javascript时检测Safari,Chrome,IE,Firefox和Opera浏览器
- 无法加载资源:下载多个文件时,Safari 浏览器中的帧加载中断
- 如何防止在 Safari 中使用 javascript 设置高度后在页面加载时运行过渡
- JavaScript 不会在 Firefox 和 Safari 中重新加载帧
- Javascript 在加载 200mb 的新 Images() 后在 Safari / iPad2 中运行缓慢.为什么
- 错误 JQuery 函数加载图像预览与 Safari 浏览器
- 应用程序缓存清单在Firefox中未加载,在Chrome和Safari中正常
- 单击后退按钮时阻止从缓存加载safari
- jScrollPane加载Safari中的动态内容分隔页