search

Home  >  Q&A  >  body text

javascript - 用jQuery的append方法插入script节点时,为何请求相应的js资源文件会附带随机的字符串?

如果直接将script节点以下例子的方式(或其他appendTo等方法)插入文档中时,相应的js文件资源请求,总是带有后缀 “?_="和一串随机数字,有点类似版本号。而且每次刷新页面时,这个随机数字字符串是不一样的,这样导致每次都重新请求和下载该资源,而不使用缓存。

$("body").append('<script src="http://libs.baidu.com/jquery/1.9.1/jquery.min.js"></script>')

使用 以下 或 document.write 原生来写是没有上面那样的问题。

var elem = document.createElement('script');
elem.src = "http://libs.useso.com/js/jquery/1.9.1/jquery.min.js";
document.querySelector('body').appendChild(elem);

那么 jQuery到底封装了什么呢,看 源代码 也看不出个所以然,望哪位高人能指点迷津一下。

PHP中文网PHP中文网2828 days ago700

reply all(2)I'll reply

  • ringa_lee

    ringa_lee2017-04-10 15:47:54

    https://github.com/jquery/jquery/blob/master/src/ajax/script.js#L25

    $.ajaxSetup({
      cache: true,
    });

    reply
    0
  • 怪我咯

    怪我咯2017-04-10 15:47:54

    特地去看了下源码

    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 );
            }
        });
    }
    
    domManip: function( args, callback ) {
    
        // Flatten any nested arrays
        args = concat.apply( [], args );
    
        var fragment, first, scripts, hasScripts, node, doc,
            i = 0,
            l = this.length,
            set = this,
            iNoClone = l - 1,
            value = args[ 0 ],
            isFunction = jQuery.isFunction( value );
    
        // We can't cloneNode fragments that contain checked, in WebKit
        if ( isFunction ||
                ( l > 1 && typeof value === "string" &&
                    !support.checkClone && rchecked.test( value ) ) ) {
            return this.each(function( index ) {
                var self = set.eq( index );
                if ( isFunction ) {
                    args[ 0 ] = value.call( this, index, self.html() );
                }
                self.domManip( args, callback );
            });
        }
    
        if ( l ) {
            fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
            first = fragment.firstChild;
    
            if ( fragment.childNodes.length === 1 ) {
                fragment = first;
            }
    
            if ( first ) {
                scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
                hasScripts = scripts.length;
    
                // Use the original fragment for the last item instead of the first because it can end up
                // being emptied incorrectly in certain situations (#8070).
                for ( ; i < l; i++ ) {
                    node = fragment;
    
                    if ( i !== iNoClone ) {
                        node = jQuery.clone( node, true, true );
    
                        // Keep references to cloned scripts for later restoration
                        if ( hasScripts ) {
                            // Support: QtWebKit
                            // jQuery.merge because push.apply(_, arraylike) throws
                            jQuery.merge( scripts, getAll( node, "script" ) );
                        }
                    }
    
                    callback.call( this[ i ], node, i );
                }
    
                if ( hasScripts ) {
                    doc = scripts[ scripts.length - 1 ].ownerDocument;
    
                    // Reenable scripts
                    jQuery.map( scripts, restoreScript );
    
                    // Evaluate executable scripts on first document insertion
                    for ( i = 0; i < hasScripts; i++ ) {
                        node = scripts[ i ];
                        if ( rscriptType.test( node.type || "" ) &&
                            !data_priv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
    
                            if ( node.src ) {
                                // Optional AJAX dependency, but won't run scripts if not present
                                if ( jQuery._evalUrl ) {
                                    jQuery._evalUrl( node.src );
                                }
                            } else {
                                jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) );
                            }
                        }
                    }
                }
            }
        }
    
        return this;
    }
    

    在domManip方法中找到这行代码

    callback.call( this[ i ], node, i );

    这个是往DOM中插入script标签的,不过插入的是这个玩意儿,代码执行到这

    这里是当前Element里的结构

    这个时候jQuery已经偷梁换柱了,拷贝了我们插入的内容,并修改了类型。类型不对,根本没有当作脚本解析。所以并不会去请求js。
    代码继续往下跑,最后执行了这个

    jQuery._evalUrl( node.src );
    
    jQuery._evalUrl = function( url ) {
        return jQuery.ajax({
            url: url,
            type: "GET",
            dataType: "script",
            async: false,
            global: false,
            "throws": true
        });
    };

    是jQuery自己发起的get请求。到这,这里的随机数字怎么出现很明显了,是ajax里的配置。@Chobits的回答。

    以上

    reply
    0
  • Cancelreply