以下のコードがスクリプト要素をDOMに追加しない理由は何ですか?
var code = "<script></script>";
$("#someElement").append(code);
以下のコードがスクリプト要素をDOMに追加しない理由は何ですか?
var code = "<script></script>";
$("#someElement").append(code);
回答:
一部のブラウザでは、直接変更したときに一部の変更が尊重されない(つまり、スクリプトタグで試行しているようなテキストからHTMLを作成する)が、組み込みコマンドで変更すると問題が発生する物事はうまくいきます。これを試して:
var script = document.createElement( 'script' );
script.type = 'text/javascript';
script.src = url;
$("#someElement").append( script );
From:jQueryのJSON
$("#someElement")[0].appendChild( script );
良いニュースは:
100%機能しています。
のようなスクリプトタグ内に何かを追加するだけalert('voila!');
です。右の質問はあなたがおそらく聞きしたい場合があり、「なぜ私はDOMでそれを見ていません?」。
Karl SwedbergがjQuery APIサイトの訪問者のコメントに良い説明をしました。私はしませんあなたが直接読み取ることができ、すべての彼の言葉を繰り返したいが、ここで(私はそこにコメントをナビゲートするハード、それを発見しました)。
jQueryのすべての挿入メソッドは、内部でdomManip関数を使用して、DOMに挿入される前後に要素をクリーンアップ/処理します。domManip関数が行うことの1つは、挿入しようとしているスクリプト要素を引き出して、DOMフラグメントの残りを挿入するのではなく、「evalScriptルーチン」を介して実行することです。スクリプトを個別に挿入して評価し、DOMから削除します。
jQueryがこれを行う理由の1つは、特定の状況でスクリプトを挿入するときにInternet Explorerで発生する可能性がある「アクセスが拒否されました」エラーを回避するためだと思います。また、挿入してDOM内を移動する包含要素内にある場合、同じスクリプトを繰り返し挿入/評価すること(これにより問題が発生する可能性があります)も回避されます。
次は、.append()
スクリプトを追加する関数を使用して、悪い点をまとめます。
そして悪いニュースは..
コードをデバッグすることはできません。
冗談ではありません。debugger;
ブレークポイントとして設定する行の間にキーワードを追加しても、ソースコードにブレークポイントが表示されずに、オブジェクトのコールスタックのみが取得されます(これは言うまでもありません)キーワードはwebkitブラウザーでのみ機能します。他のすべての主要ブラウザーはこのキーワードを省略しているようです)。
コードの機能を完全に理解している場合は、これがマイナーな欠点になります。しかし、そうしないと、debugger;
あなた(または私の)のコードのどこに問題があるのかを見つけるために、キーワードをあちこちに追加することになります。とにかく、代替手段があります。JavaScriptがHTML DOMをネイティブに操作できることを忘れないでください。
回避策。
JavaScript(jQueryではなく)を使用してHTML DOMを操作する
デバッグ機能を失いたくない場合は、JavaScriptのネイティブHTML DOM操作を使用できます。この例を考えてみましょう:
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "path/to/your/javascript.js"; // use this for linked script
script.text = "alert('voila!');" // use this for inline script
document.body.appendChild(script);
昔と同じように、それはあります。そして、メモリリークを防ぐために、参照されているすべてのオブジェクトについて、DOM内でもメモリ内でもクリーンアップすることを忘れないでください。このコードを考慮して、次のことを整理できます。
document.body.removechild(document.body.lastChild);
delete UnusedReferencedObjects; // replace UnusedReferencedObject with any object you created in the script you load.
この回避策の欠点は、誤って重複したスクリプトを追加する可能性があることです。これは悪いことです。ここから.append()
、追加する前にオブジェクト検証を追加し、追加された直後にDOMからスクリプトを削除することで、機能をわずかに模倣できます。この例を考えてみましょう:
function AddScript(url, object){
if (object != null){
// add script
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "path/to/your/javascript.js";
document.body.appendChild(script);
// remove from the dom
document.body.removeChild(document.body.lastChild);
return true;
} else {
return false;
};
};
function DeleteObject(UnusedReferencedObjects) {
delete UnusedReferencedObjects;
}
このようにして、スクリプトの重複から保護しながら、デバッグ機能を備えたスクリプトを追加できます。これは単なるプロトタイプであり、好きなように拡張できます。私はこのアプローチを使用しており、これに非常に満足しています。確か.append()
に、jQuery を使用してスクリプトを追加することは決してありません。
$.getScript
jQueryに組み込まれています。
「機能しない」とはどういう意味ですか?
jQueryは、SCRIPT要素を作成しようとしていることを検出し、グローバルコンテキスト内で要素のコンテンツを自動的に実行します。これはあなたにとってうまくいかないと私に言っていますか?-
$('#someElement').append('<script>alert("WORKING");</script>');
編集:私が言ったようにjQueryがコードを実行してSCRIPT要素を削除するため、コマンドを実行した後、DOMにSCRIPT要素が表示されていない場合(たとえばFirebugで)、SCRIPT要素を信じています常にボディに追加されます...しかし、とにかく-この状況では、配置はコード実行にまったく影響しません。
これは機能します:
$('body').append($("<script>alert('Hi!');<\/script>")[0]);
jQueryはスクリプトを巧妙に処理しているようですので、jQueryオブジェクトではなくhtml要素を追加する必要があります。
これは役立つかもしれません:
var fileref=document.createElement('script');
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src","scriptAnalytics.js");
document.getElementsByTagName("head")[0].appendChild(fileref);
<script>
...
...jQuery("<script></script>")...
...
</script>
</script>
文字列リテラル内では避けるために、スクリプト全体を終了させる"</scr" + "ipt>"
代わりに使用することができます。
"\x3cscript\x3e\x3c/script\x3e"
。XHTMLでは、コメントアウトされたCDATAブロックを配置するだけです。
</
許されないことです。stackoverflow.com/questions/236073/…を
これが私が最良の解決策だと思うものです。Google Analyticsはこの方法で注入されます。
var (function(){
var p="https:" == document.location.protocol ? "https://" : "http://";
d=document,
g=d.createElement('script'),
s=d.getElementsByTagName('script')[0];
g.type='text/javascript';
g.src=p+'url-to-your-script.js';
s.parentNode.insertBefore(g,s); })();
スクリプトDOM要素を作成するためにjQueryは必要ありません。これは、バニラES6で次のように実行できます。
const script = "console.log('Did it work?')"
new Promise((resolve, reject) => {
(function(i,s,o,g,r,a,m){
a=s.createElement(o),m=s.getElementsByTagName(o)[0];
a.innerText=g;
a.onload=r;m.parentNode.insertBefore(a,m)}
)(window,document,'script',script, resolve())
}).then(() => console.log('Sure did!'))
これをでラップする必要はありませんがPromise
、これにより、スクリプトのロード時にプロミスを解決できるため、長時間実行されるスクリプトの競合状態を回避できます。
本文にスクリプトを追加:
$(document).ready(function() {
$("<script>", { src : "bootstrap.min.js", type : "text/javascript" }).appendTo("body");
});
このように試すことができます
var code = "<script></" + "script>";
$("#someElement").append(code);
あなたができない唯一の理由"<script></script>"
は、DOMレイヤーがjsとHTMLを解析できないため、JavaScript内では文字列が許可されないためです。
私が書いたnpm
、あなたがHTML文字列を取ることができますパッケージをスクリプトタグを含むとしながら、コンテナに追加したスクリプトを実行します
例:
import appendHtml from 'appendhtml';
const html = '<p>Hello</p><script src="some_js_file.js"></script>';
const container = document.getElementById('some-div');
await appendHtml(html, container);
// appendHtml returns a Promise, some_js_file.js is now loaded and executed (note the await)
ここでそれを見つけてください:https://www.npmjs.com/package/appendhtml
jQueryで解析して要素を作成するだけです。
<div id="someElement"></div>
<script>
var code = "<script>alert(123);<\/script>";
$("#someElement").append($(code));
</script>