3

外部スクリプトをロードし、ロード時にいくつかのコードを実行することになっている次のコードがあります。

$('<script/>', {
    type: 'text/javascript',
    src: 'https://raw.github.com/einars/js-beautify/master/beautify.js'
}).on('load', function() {
    alert('jsb loaded' + typeof js_beautify);
}).appendTo('body');

ただし、スクリプトが適切にロードされているにもかかわらず、イベントが発生することはありません。

window.setTimeout(function() {
    alert(typeof js_beautify);
}, 1000);

これは問題なく警告functionします。

デモ: http://jsfiddle.net/ThiefMaster/x2b9x/

4

2 に答える 2

2

を呼び出す必要があります$.getScript()。これはまさにそれを行い、正しく動作します。

于 2012-05-30T19:12:58.423 に答える
2

(jQuery:2.0.3) appendTo() による動的スクリプト タグ インジェクションでロード イベントがトリガーされない 2 つの理由:

  • load イベントはバブル イベントではありません。呼び出されたハンドラーは、その特定の要素のみにフックされます
  • appendTo() は実際には、コードによって提供された要素を期待どおりに DOM に挿入しません

getScript() DOM 関数を直接使用する

document.head.appendChild( script[ 0 ] );

script タグ要素を挿入します。これにより、タグ要素が実際に DOM に追加されます。appendTo() は代わりに Ajax を使用してソース URL からスクリプトをロードしようとします。次に、スクリプト オブジェクトではなくウィンドウ オブジェクトに対してロード イベントがトリガーされます。

以下は、理由を知るための jQuery.appendTo() の詳細テストです。

                var $script = $("<script>", {
                    src: this.options.url_js,
                    "data-widget": this.widgetFullName,
                    type:"text/javascript"
                }).on(
                    "load error",
                    function( evt ) {
                        script.remove();
                        if ( evt ) {
                            alert( evt.type === "error" ? 404 : 200, evt.type );
                        }
                    }
                ).appendTo("head");
  1. jQuery.on() は、要素をキーとして使用して、イベント ハンドラを「data_priv」に登録します。
  2. イベントが発生すると、jQuery は「jQuery.event.dispatch.apply( eventHandle.elem, arguments )」を使用してハンドラーを呼び出します。

jQuery.appendTo() は「追加」のエイリアスです。実際のコードは

   append: function() {
    return this.domManip( arguments, function( elem ) {
        if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
            var target = manipulationTarget( this, elem );
            target.appendChild( elem );
        }
    });
}

実際に要素を DOM に挿入する前に、domManip() を使用していくつかの ajax 処理を行います。

  domManip: function( args, callback, allowIntersection ) {

この関数には 2 つの重要な変数があり、1 つは「値」、2 番目は「ノード」です。「値」は変数「$script」です。実際に挿入された要素は「ノード」であり、「$script」ではありません

  callback.call( this[ i ], node, i ); //inject the element into the DOM  

変数ノードと値のFirefox比較

そのため、「$script」の「load」イベント ハンドラはまったく呼び出されません。

ただし、このロード イベントは 2 回トリガーされます。1 つはロードされた要素 (ここではノード) 用で、もう 1 つはウィンドウ オブジェクト用です。ハンドラーがウィンドウ オブジェクトにフックされている場合、それが呼び出されます。

于 2013-11-20T03:39:32.283 に答える