에서를 사용하여 일부 스크립트를 페이지에로드하려고 innerHTML
했습니다 <div>
. 스크립트가 DOM으로로드되는 것처럼 보이지만 (적어도 Firefox 및 Chrome에서는) 실행되지 않습니다. 스크립트를 삽입 할 때 스크립트를 실행하는 방법이 innerHTML
있습니까?
샘플 코드 :
<!DOCTYPE html>
<html>
<body onload="document.getElementById('loader').innerHTML = '<script>alert(\'hi\')<\/script>'">
Shouldn't an alert saying 'hi' appear?
<div id="loader"></div>
</body>
</html>
답변
DOM 텍스트로 삽입 한 스크립트 코드를 실행 하려면 eval () 을 사용해야 합니다.
MooTools가 자동으로이를 수행하므로 jQuery도 버전에 따라 다릅니다. jQuery 버전 1.6 이상은을 사용 eval
합니다. 이렇게하면 <script>
태그 를 파싱하고 콘텐츠를 빠져 나오는 많은 번거 로움 과 다른 “gotchas”를 줄일 수 있습니다.
당신이거야 일반적으로 경우에 eval()
그것은 자신을, 당신은 / 생성과 같은 모든 HTML 마크 업없이 스크립트 코드를 보내려면 <script>
이되지 바와 같이, eval()
제대로.
답변
문제에 대한 매우 흥미로운 해결책은 다음과 같습니다.
http://24ways.org/2005/have-your-dom-and-script-it-too
따라서 스크립트 태그 대신 이것을 사용하십시오.
<img src="empty.gif" onload="alert('test');this.parentNode.removeChild(this);" />
답변
다음은 모든 스크립트를 실행 가능한 스크립트로 재귀 적으로 대체하는 방법입니다.
function nodeScriptReplace(node) {
if ( nodeScriptIs(node) === true ) {
node.parentNode.replaceChild( nodeScriptClone(node) , node );
}
else {
var i = 0;
var children = node.childNodes;
while ( i < children.length ) {
nodeScriptReplace( children[i++] );
}
}
return node;
}
function nodeScriptIs(node) {
return node.tagName === 'SCRIPT';
}
function nodeScriptClone(node){
var script = document.createElement("script");
script.text = node.innerHTML;
for( var i = node.attributes.length-1; i >= 0; i-- ) {
script.setAttribute( node.attributes[i].name, node.attributes[i].value );
}
return script;
}
호출 예 :
nodeScriptReplace(document.getElementsByTagName("body")[0]);
답변
스크립트를 작성한 다음 컨텐츠를 삽입 할 수 있습니다.
var g = document.createElement('script');
var s = document.getElementsByTagName('script')[0];
g.text = "alert(\"hi\");"
s.parentNode.insertBefore(g, s);
이것은 모든 브라우저에서 작동합니다 🙂
답변
이 코드를 사용했는데 정상적으로 작동합니다.
var arr = MyDiv.getElementsByTagName('script')
for (var n = 0; n < arr.length; n++)
eval(arr[n].innerHTML)//run script inside div
답변
innerHTML에서이 문제가 발생하여 Reactjs 애플리케이션의 “head”태그에 Hotjar 스크립트를 추가해야했으며 추가 직후 실행해야했습니다.
“헤드”태그로 동적 노드를 가져 오기위한 좋은 솔루션 중 하나는 React-helment 모듈입니다.
또한 제안 된 문제에 대한 유용한 솔루션이 있습니다.
innerHTML에 스크립트 태그가 없습니다!
HTML5에서는 innerHTML 속성을 사용하여 스크립트 태그를 동적으로 추가 할 수 없습니다. 따라서 다음이 실행되지 않으며 Hello World!라는 경고가 표시되지 않습니다.
element.innerHTML = "<script>alert('Hello World!')</script>";
이것은 HTML5 사양에 설명되어 있습니다.
참고 : innerHTML을 사용하여 삽입 된 스크립트 요소는 삽입 될 때 실행되지 않습니다.
그러나 이것이 innerHTML이 사이트 간 스크립팅으로부터 안전하다는 것을 의미하지는 않습니다. MDN의 innerHTML 페이지 에 설명 된대로 태그를 사용하지 않고 innerHTML을 통해 JavaScript를 실행할 수 있습니다 .
솔루션 : 동적으로 스크립트 추가
스크립트 태그를 동적으로 추가하려면 새 스크립트 요소를 작성하여 대상 요소에 추가해야합니다.
외부 스크립트에 대해이 작업을 수행 할 수 있습니다.
var newScript = document.createElement("script");
newScript.src = "http://www.example.com/my-script.js";
target.appendChild(newScript);
인라인 스크립트 :
var newScript = document.createElement("script");
var inlineScript = document.createTextNode("alert('Hello World!');");
newScript.appendChild(inlineScript);
target.appendChild(newScript);
답변
사람이 아직도이 일을하려고 들어, 아니, 당신은 사용하여 스크립트를 삽입 할 수 innerHTML
있지만, 사용하여 스크립트 태그에 문자열을로드 할 수있다 Blob
및 URL.createObjectURL
.
문자열을 스크립트로 실행하고 약속을 통해 반환되는 스크립트의 ‘내보내기’를 얻을 수있는 예제를 만들었습니다.
function loadScript(scriptContent, moduleId) {
// create the script tag
var scriptElement = document.createElement('SCRIPT');
// create a promise which will resolve to the script's 'exports'
// (i.e., the value returned by the script)
var promise = new Promise(function(resolve) {
scriptElement.onload = function() {
var exports = window["__loadScript_exports_" + moduleId];
delete window["__loadScript_exports_" + moduleId];
resolve(exports);
}
});
// wrap the script contents to expose exports through a special property
// the promise will access the exports this way
var wrappedScriptContent =
"(function() { window['__loadScript_exports_" + moduleId + "'] = " +
scriptContent + "})()";
// create a blob from the wrapped script content
var scriptBlob = new Blob([wrappedScriptContent], {type: 'text/javascript'});
// set the id attribute
scriptElement.id = "__loadScript_module_" + moduleId;
// set the src attribute to the blob's object url
// (this is the part that makes it work)
scriptElement.src = URL.createObjectURL(scriptBlob);
// append the script element
document.body.appendChild(scriptElement);
// return the promise, which will resolve to the script's exports
return promise;
}
...
function doTheThing() {
// no evals
loadScript('5 + 5').then(function(exports) {
// should log 10
console.log(exports)
});
}
실제 구현에서 이것을 단순화 했으므로 버그가 없다고 약속하지 않습니다. 그러나 원리는 효과가 있습니다.
스크립트가 실행 된 후 다시 값을 얻는 것에 신경 쓰지 않으면 훨씬 쉽습니다. Promise
and onload
비트 는 그대로 두십시오 . 스크립트를 래핑하거나 전역 window.__load_script_exports_
속성을 만들 필요조차 없습니다 .