HTML JavaScript延迟下载img src直到DOM节点
HTML JavaScript delay downloading img src until node in DOM
嗨,我有标记从服务器发送给我,我把它设置为div元素的innerHTML,目的是遍历树,找到图像节点,并改变它们的src值。是否有一种方法可以防止原始src值被下载?
这是我正在做的
function replaceImageSrcsInMarkup(markup) {
var div = document.createElement('div');
div.innerHTML = markup;
var images = div.getElementsByTagName('img');
images.forEach(replaceSrc);
return div.innerHTML;
}
问题是,在浏览器中,只要你这样做:var img = document.createElement('img'); img.src = 'someurl.com'
浏览器向someurl.com
发出请求。有没有一种方法可以防止这种情况,而不需要自己解析标记?如果没有其他方法,谁知道用尽可能少的代码解析标记以实现我的目标的好方法?
我知道您已经对您的解决方案感到满意了,但是我认为值得与未来的用户分享一个安全的方法。
你现在可以简单地使用DOMParser
对象从你的HTML字符串生成一个外部文档,而不是使用div
创建你当前的document
作为容器。
DOMParser特别避免了问题中提到的陷阱和其他威胁:不下载img
src
,不执行JavaScript,甚至在元素属性中。
所以在你的情况下,你可以安全地这样做:
function replaceImageSrcsInMarkup(markup) {
var parser = new DOMParser(),
doc = parser.parseFromString(markup, "text/html");
// Manipulate `doc` as a regular document
var images = doc.getElementsByTagName('img');
for (var i = 0; i < images.length; i += 1) {
replaceSrc(images[i]);
}
return doc.body.innerHTML;
}
演示:http://jsfiddle.net/94b7gyg9/1/
注意:在你当前的代码中,浏览器仍然会尝试下载最初在你的img
节点src
属性中指定的资源,即使你在JS执行结束之前改变它。在这个演示中跟踪网络事务:http://jsfiddle.net/94b7gyg9/
在更改img源之前,不要将新标记附加到DOM中,而是创建一个元素,设置其内部HTML,更改图像源,然后最后将更改的标记附加到页面中。
这是一个完整的示例。
<!DOCTYPE html>
<html>
<head>
<script>
"use strict";
function byId(id,parent){return (parent == undefined ? document : parent).getElementById(id);}
//function allByClass(className,parent){return (parent == undefined ? document : parent).getElementsByClassName(className);}
function allByTag(tagName,parent){return (parent == undefined ? document : parent).getElementsByTagName(tagName);}
function newEl(tag){return document.createElement(tag);}
//function newTxt(txt){return document.createTextNode(txt);}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
window.addEventListener('load', onDocLoaded, false);
function onDocLoaded()
{
byId('goBtn').addEventListener('click', onGoBtnClick, false);
}
var dummyString = "<img src='img/girl.png'/><img src='img/gfx07.jpg'/>";
function onGoBtnClick(evt)
{
var div = newEl('div');
div.innerHTML = dummyString;
var mImgs = allByTag('img', div);
for (var i=0, n=mImgs.length; i<n; i++)
{
mImgs[i].src = "img/murderface.jpg";
}
document.body.appendChild(div);
}
</script>
<style>
</style>
</head>
<body>
<button id='goBtn'>GO!</button>
</body>
</html>
您可以使用正则表达式直接解析标记字符串来替换img src。搜索字符串中所有的img src url,然后用新的url替换它们。
var regex = /<img[^>]+src="?([^"'s]+)"?'s*'/>/g;
var imgUrls = [];
while ( m = regex.exec( markup ) ) {
imgUrls.push( m[1] );
}
imgUrls.forEach(function(url) {
markup = markup.replace(url,'new-url');
});
另一个解决方案可能是,如果您可以访问它,将所有img src设置为空字符串,并将url放在data-src属性中。让标记字符串看起来像这样标记= '"
那么将这个标记设置为div.innerHTML将不会触发从浏览器的任何下载。您仍然可以使用常规DOM选择器解析它。
div.innerHTML = markup;
var images = div.getElementsByTagName('img');
images.forEach(function(img){
var oldSrc = img.getAttribute('data-src');
img.setAttribute('src', 'new-url');
});
- 在单击任何位置时隐藏元素,而不检查每次DOM单击
- 是否有任何snippet或jQuery插件可以列出easylist.txt模式匹配的DOM中的所有元素
- 在不使用JQuery的情况下隐藏DOM中的选定元素
- 如何在DOM元素上按类型构建此函数
- Windows形成web浏览器控件和Javascript更改的DOM
- 同步调用,直到用户通过angular验证为访问者
- Datatables:通过DOM数据源中的名称引用列
- 在DOM中查找一个模式并替换它's的内容使用jquery
- Javascript没有't更新DOM,直到用户交互
- jQuery append in loop - DOM 直到最后才更新
- 选择所有DOM元素,直到出现几个DOM元素中的一个为止
- 延迟javascript执行,直到DOM更改完成
- JavaScript似乎加载到DOM中,但直到在chrome控制台运行才执行
- 继续尝试函数,直到所需的DOM元素加载
- HTML JavaScript延迟下载img src直到DOM节点
- DOM中的新SVG元素,通过JavaScript添加,直到鼠标up才呈现
- 如何遍历DOM,直到到达一个类
- Angular.js显示加载动画,直到DOM准备好
- 暂停jQuery就绪事件,直到多个HTML DOM更新完成
- 追加对象到DOM,缓冲事件直到下一个滴答