请考虑以下JavaScript代码片段:
const app = document.getElementById('root');
const svg = `<svg version="1.1" id="Layer_1"...`;
const obj = document.createElement('object');
obj.setAttribute('type', 'image/svg+xml');
obj.setAttribute('data', `data:image/svg+xml; base64,${btoa(svg)}`);
app.appendChild(obj);
setTimeout(() => {
console.log(obj.contentDocument.querySelector('svg'));
}, 1500);
(有关完整示例,请参阅 )
运行此命令时,控制台(Google Chrome)中会显示以下错误:
HTMLObjectElement未捕获DOMException:未能从“”HTMLObjectElement“”中读取“”contentDocument“”属性:阻止具有源“"https://fiddle.jshell.net”“的帧访问跨域帧。”“在setTimeout (https://fiddle.jshell.net/_display:77:19)
考虑到这一点;
contentDocument
时,这为什么被认为是跨域请求?发布于 2017-10-27 22:34:47
这里的问题是,data:
URLs are treated as having a unique origin与创建嵌入式data:
上下文的上下文的来源不同:
注意:现代浏览器将数据URL视为唯一的不透明来源,而不是继承负责导航的设置对象的来源。
WHATWG规范描述了how content documents are accessed,它包括交叉来源检查。WHATWG same-origin comparison永远不会将传统方案-主机-端口“元组”来源等同于“不透明”的data:
来源。
取而代之的是,使用带有URL.createObjectURL
的Blob
来生成一个同源的临时URL,其内容将由外部环境读取:
var svgUrl = URL.createObjectURL(new Blob([svg], {'type':'image/svg+xml'}));
obj.setAttribute('data', svgUrl);
我不知道这种方法被允许而原始data:
URL不被允许的安全原因,但它似乎确实有效。(我猜是因为生成的URL只能由生成它的源读取,而data:
URL不知道如何只由其原始上下文的原始上下文读取。)
另请注意,某些版本的Internet Explorer支持createObjectURL
,但错误地将生成的URL视为具有空源,这将导致此方法失败。
其他选项包括:
SVG不要使用SVG,而是从创建
contentDocument
的页面的同一来源提供data:
内容,并使用inline element (fiddle):const obj = document.createElement('div');obj.innerHTML = svg;app.appendChild(obj);setTimeout(() => { console.log(obj.querySelector('svg'));},1500);
大多数浏览器都支持内联<svg>
元素(特别是IE 9.0+;其他浏览器要早得多)。这意味着你可以根据你想要对SVG做什么来做
DOMParser
和做DOM探索/操作。var oParser =新的DOMParser();var svgDOM = oParser.parseFromString(svg,“文本/xml”);var
但是DOM模型将与在<object>
中呈现的SVG分开。要更改<object>
,您需要序列化已解析的DOM结构,并将其重新推送到data
属性:
var oSerializer =新数据();var sXML = oSerializer.serializeToString(svgDOM);obj.setAttribute('data',data:image/svg+xml; base64,${btoa(sXML)}
);
这看起来性能不是很好,因为它需要浏览器重新解析一个全新的SVG文档,但它将绕过安全限制。
可以将<object>
看作一个单向黑洞,它可以接收要呈现的SVG信息,但不会公开任何返回的信息。不过,这不是一个信息学问题,因为您拥有刚刚输入到<object>
中的信息:contentDocument
可以告诉您的信息都是您已经知道的。
但是,如果您想通过将侦听器附加到在主页上执行代码的SVG结构中的组件来使SVG中的组件具有交互性,我认为这种方法是行不通的。与<iframe>
.一样,<object>
与其周围页面之间的分隔具有相同的嵌入关系
发布于 2017-10-27 22:19:21
因为object标记在HTML文档中定义了一个嵌入的对象,所以它不是文档本身的一部分,因此必须像框架一样尊重CORS
here清楚地指出,object标记的内容被视为外部资源
元素表示外部资源,可以将其视为图像、嵌套的浏览上下文或要由插件处理的资源。
https://stackoverflow.com/questions/46929730
复制相似问题