用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到底封装了什么呢,看 源代码 也看不出个所以然,望哪位高人能指点迷津一下。
kbmgs
9 years, 2 months ago
Answers
特地去看了下源码
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的回答。
以上
yamada
answered 9 years, 2 months ago
https://github.com/jquery/jquery/blob/master/src/ajax/script.js#L25
$.ajaxSetup({
cache: true,
});
dafanxu
answered 9 years, 2 months ago