- 浏览: 522031 次
- 性别:
- 来自: 北京
博客专栏
-
jQuery技术内幕
浏览量:201225
最新评论
-
青春依旧:
学习html5哪里好?当然华清远见是首选!
[原创] jQuery源码分析-01总体架构 -
追梦1819:
[size=x-small][color=red][/colo ...
[原创] jQuery源码分析-04 选择器-Sizzle-设计思路 -
niuqiang2008:
学习学习
[原创] jQuery源码分析-04 选择器-Sizzle-工作原理 -
liuweihug:
jquery 解析正则表达式及常见的Regex规则和表达式 - ...
[原创] jQuery源码分析-02正则表达式-RegExp-常用正则表达式 -
liang8768:
mark!!!
[原创] jQuery源码分析-00前言开光
边读边写,不正确的地方,还请各位告诉我,多多交流共同学习。
15.4 AJAX中的前置过滤器和请求分发器
自jQuery1.5以后,AJAX模块提供了三个新的方法用于管理、扩展AJAX请求,分别是:
l 前置过滤器 jQuery. ajaxPrefilter
l 请求分发器 jQuery. ajaxTransport,
l 类型转换器 ajaxConvert
这里先分析前置过滤器和请求分发器,类型转换器下一节再讲。
15.4.1 前置过滤器和请求分发器的初始化
前置过滤器和请求分发器在执行时,分别遍历内部变量prefilters和transports,这两个变量在jQuery加载完毕后立即初始化,初始化的过程很有意思。
首先,prefilters和transports被置为空对象:
prefilters = {}, // 过滤器 transports = {}, // 分发器 |
然后,创建jQuery.ajaxPrefilter和jQuery.ajaxTransport,这两个方法都调用了内部函数addToPrefiltersOrTransports,addToPrefiltersOrTransports返回一个匿名闭包函数,这个匿名闭包函数负责将单一前置过滤和单一请求分发器分别放入prefilters和transports。我们知道闭包会保持对它所在环境变量的引用,而jQuery.ajaxPrefilter和jQuery.ajaxTransport的实现又完全一样,都是对Map结构的对象进行赋值操作,因此这里利用闭包的特性巧妙的将两个方法的实现合二为一。函数addToPrefiltersOrTransports可视为模板模式的一种实现。
ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), // 通过闭包保持对prefilters的引用,将前置过滤器添加到prefilters ajaxTransport: addToPrefiltersOrTransports( transports ), // 通过闭包保持对transports的引用,将请求分发器添加到transports
// 添加全局前置过滤器或请求分发器,过滤器的在发送之前调用,分发器用来区分ajax请求和script标签请求 function addToPrefiltersOrTransports( structure ) { // 通过闭包访问structure // 之所以能同时支持Prefilters和Transports,关键在于structure引用的时哪个对象 // dataTypeExpression is optional and defaults to "*" // dataTypeExpression是可选参数,默认为* return function( dataTypeExpression, func ) { // 修正参数 if ( typeof dataTypeExpression !== "string" ) { func = dataTypeExpression; dataTypeExpression = "*"; }
if ( jQuery.isFunction( func ) ) { var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ), // 用空格分割数据类型表达式dataTypeExpression i = 0, length = dataTypes.length, dataType, list, placeBefore;
// For each dataType in the dataTypeExpression for(; i < length; i++ ) { dataType = dataTypes[ i ]; // We control if we're asked to add before // any existing element // 如果以+开头,过滤+ placeBefore = /^\+/.test( dataType ); if ( placeBefore ) { dataType = dataType.substr( 1 ) || "*"; } list = structure[ dataType ] = structure[ dataType ] || []; // then we add to the structure accordingly // 如果以+开头,则插入开始位置,否则添加到末尾 // 实际上操作的是structure list[ placeBefore ? "unshift" : "push" ]( func ); } } }; } |
最后,分别调用jQuery.ajaxPrefilter和jQuery.ajaxTransport填充prefilters和transports.
填充prefilters:
// Detect, normalize options and install callbacks for jsonp requests // 向前置过滤器对象中添加特定类型的过滤器 // 添加的过滤器将格式化参数,并且为jsonp请求增加callbacks // MARK:AJAX模块初始化 jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
var inspectData = s.contentType === "application/x-www-form-urlencoded" && ( typeof s.data === "string" ); // 如果是表单提交,则需要检查数据
// 这个方法只处理jsonp,如果json的url或data有jsonp的特征,会被当成jsonp处理 // 触发jsonp的3种方式: if ( s.dataTypes[ 0 ] === "jsonp" || // 如果是jsonp s.jsonp !== false && ( jsre.test( s.url ) || // 未禁止jsonp,s.url中包含=?& =?$ ?? inspectData && jsre.test( s.data ) ) ) { // s.data中包含=?& =?$ ??
var responseContainer, jsonpCallback = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback, // s.jsonpCallback时函数,则执行函数用返回值做为回调函数名 previous = window[ jsonpCallback ], url = s.url, data = s.data, // jsre = /(\=)\?(&|$)|\?\?/i; // =?& =?$ ?? replace = "$1" + jsonpCallback + "$2"; // $1 =, $2 &|$
if ( s.jsonp !== false ) { url = url.replace( jsre, replace ); // 将回调函数名插入url if ( s.url === url ) { // 如果url没有变化,则尝试修改data if ( inspectData ) { data = data.replace( jsre, replace ); // 将回调函数名插入data } if ( s.data === data ) { // 如果data也没有变化 // Add callback manually url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback; // 自动再url后附加回调函数名 } } }
// 存储可能改变过的url、data s.url = url; s.data = data;
// Install callback window[ jsonpCallback ] = function( response ) { // 在window上注册回调函数 responseContainer = [ response ]; };
// Clean-up function jqXHR.always(function() { // Set callback back to previous value // 将备份的previous函数恢复 window[ jsonpCallback ] = previous; // Call if it was a function and we have a response // 响应完成时调用jsonp回调函数,问题是这个函数不是自动执行的么? if ( responseContainer && jQuery.isFunction( previous ) ) { window[ jsonpCallback ]( responseContainer[ 0 ] ); // 为什么要再次执行previous呢? } });
// Use data converter to retrieve json after script execution s.converters["script json"] = function() { if ( !responseContainer ) { // 如果 jQuery.error( jsonpCallback + " was not called" ); } return responseContainer[ 0 ]; // 因为是作为方法的参数传入,本身就是一个json对象,不需要再做转换 };
// force json dataType s.dataTypes[ 0 ] = "json"; // 强制为json
// Delegate to script return "script"; // jsonp > json } }); // Handle cache's special case and global // 设置script的前置过滤器,script并不一定意思着跨域 // MARK:AJAX模块初始化 jQuery.ajaxPrefilter( "script", function( s ) { if ( s.cache === undefined ) { // 如果缓存未设置,则设置false s.cache = false; } if ( s.crossDomain ) { // 跨域未被禁用,强制类型为GET,不触发全局时间 s.type = "GET"; s.global = false; } }); |
填充transports:
// Bind script tag hack transport // 绑定script分发器,通过在header中创建script标签异步载入js,实现过程很简介 // MARK:AJAX模块初始化 jQuery.ajaxTransport( "script", function(s) {
// This transport only deals with cross domain requests if ( s.crossDomain ) { // script可能时json或jsonp,jsonp需要跨域,ajax模块大约有1/3的代码时跨域的 // 如果在本域中设置了跨域会怎么处理呢?
var script, head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement; // 充分利用布尔表达式的计算顺序
return {
send: function( _, callback ) { // 提供与同域请求一致的接口
script = document.createElement( "script" ); // 通过创script标签来实现
script.async = "async";
if ( s.scriptCharset ) { script.charset = s.scriptCharset; // 字符集 }
script.src = s.url; // 动态载入
// Attach handlers for all browsers script.onload = script.onreadystatechange = function( _, isAbort ) {
if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
// Handle memory leak in IE script.onload = script.onreadystatechange = null; // onload事件触发后,销毁事件句柄,因为IE内存泄漏?
// Remove the script if ( head && script.parentNode ) { head.removeChild( script ); // onloda后,删除script节点 }
// Dereference the script script = undefined; // 注销script变量
// Callback if not abort if ( !isAbort ) { callback( 200, "success" ); // 执行回调函数,200为HTTP状态码 } } }; // Use insertBefore instead of appendChild to circumvent an IE6 bug. // This arises when a base node is used (#2709 and #4378). // 用insertBefore代替appendChild,如果IE6的bug head.insertBefore( script, head.firstChild ); },
abort: function() { if ( script ) { script.onload( 0, 1 ); // 手动触发onload事件,jqXHR状态码为0,HTTP状态码为1xx } } }; } });
// Create transport if the browser can provide an xhr if ( jQuery.support.ajax ) { // MARK:AJAX模块初始化 // 普通AJAX请求分发器,dataType默认为* jQuery.ajaxTransport(function( s ) { // * // Cross domain only allowed if supported through XMLHttpRequest // 如果不是跨域请求,或支持身份验证 if ( !s.crossDomain || jQuery.support.cors ) {
var callback;
return { send: function( headers, complete ) {
// Get a new xhr // 创建一个XHR var xhr = s.xhr(), handle, i;
// Open the socket // Passing null username, generates a login popup on Opera (#2865) // 调用XHR的open方法 if ( s.username ) { xhr.open( s.type, s.url, s.async, s.username, s.password ); // 如果需要身份验证 } else { xhr.open( s.type, s.url, s.async ); }
// Apply custom fields if provided // 在XHR上绑定自定义属性 if ( s.xhrFields ) { for ( i in s.xhrFields ) { xhr[ i ] = s.xhrFields[ i ]; } }
// Override mime type if needed // 如果有必要的话覆盖mineType,overrideMimeType并不是一个标准接口,因此需要做特性检测 if ( s.mimeType && xhr.overrideMimeType ) { xhr.overrideMimeType( s.mimeType ); }
// X-Requested-With header // For cross-domain requests, seeing as conditions for a preflight are // akin to a jigsaw puzzle, we simply never set it to be sure. // (it can always be set on a per-request basis or even using ajaxSetup) // For same-domain requests, won't change header if already provided. // X-Requested-With同样不是一个标注HTTP头,主要用于标识Ajax请求.大部分JavaScript框架将这个头设置为XMLHttpRequest if ( !s.crossDomain && !headers["X-Requested-With"] ) { headers[ "X-Requested-With" ] = "XMLHttpRequest"; }
// Need an extra try/catch for cross domain requests in Firefox 3 // 设置请求头 try { for ( i in headers ) { xhr.setRequestHeader( i, headers[ i ] ); } } catch( _ ) {}
// Do send the request // This may raise an exception which is actually // handled in jQuery.ajax (so no try/catch here) // 调用XHR的send方法 xhr.send( ( s.hasContent && s.data ) || null );
// Listener // 封装回调函数 callback = function( _, isAbort ) {
var status, statusText, responseHeaders, responses, // 响应内容,格式为text:text, xml:xml xml;
// Firefox throws exceptions when accessing properties // of an xhr when a network error occured // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE) // 在FF下当网络异常时,访问XHR的属性会抛出异常 try {
// Was never called and is aborted or complete if ( callback && ( isAbort || xhr.readyState === 4 ) ) { // 4表示响应完成
// Only called once callback = undefined; // callback只调用一次,注销callback
// Do not keep as active anymore if ( handle ) { xhr.onreadystatechange = jQuery.noop; // 将onreadystatechange句柄重置为空函数 if ( xhrOnUnloadAbort ) { // 如果是界面退出导致本次请求取消 delete xhrCallbacks[ handle ]; // 注销句柄 } }
// If it's an abort if ( isAbort ) { // 如果是取消本次请求 // Abort it manually if needed if ( xhr.readyState !== 4 ) { xhr.abort(); // 调用xhr原生的abort方法 } } else { status = xhr.status; responseHeaders = xhr.getAllResponseHeaders(); responses = {}; xml = xhr.responseXML;
// Construct response list if ( xml && xml.documentElement /* #4958 */ ) { responses.xml = xml; // 提取xml } responses.text = xhr.responseText; // 提取text
// Firefox throws an exception when accessing // statusText for faulty cross-domain requests // FF在跨域请求中访问statusText会抛出异常 try { statusText = xhr.statusText; } catch( e ) { // We normalize with Webkit giving an empty statusText statusText = ""; // 像WebKit一样将statusText置为空字符串 }
// Filter status for non standard behaviors
// If the request is local and we have data: assume a success // (success with no data won't get notified, that's the best we // can do given current implementations) // 过滤不标准的服务器状态码 if ( !status && s.isLocal && !s.crossDomain ) { status = responses.text ? 200 : 404; // // IE - #1450: sometimes returns 1223 when it should be 204 // 204 No Content } else if ( status === 1223 ) { status = 204; } } } } catch( firefoxAccessException ) { if ( !isAbort ) { complete( -1, firefoxAccessException ); // 手动调用回调函数 } }
// Call complete if needed // 在回调函数的最后,如果请求完成,立即调用回调函数 if ( responses ) { complete( status, statusText, responses, responseHeaders ); } };
// if we're in sync mode or it's in cache // and has been retrieved directly (IE6 & IE7) // we need to manually fire the callback // 同步模式下:同步导致阻塞一致到服务器响应完成,所以这里可以立即调用callback if ( !s.async || xhr.readyState === 4 ) { callback(); } else { handle = ++xhrId; // 请求计数 // 如果时页面退出导致本次请求取消,修正在IE下不断开连接的bug if ( xhrOnUnloadAbort ) { // Create the active xhrs callbacks list if needed // and attach the unload handler if ( !xhrCallbacks ) { xhrCallbacks = {}; jQuery( window ).unload( xhrOnUnloadAbort ); // 手动触发页面销毁事件 } // Add to list of active xhrs callbacks // 将回调函数存储在全局变量中,以便在响应完成或页面退出时能注销回调函数 xhrCallbacks[ handle ] = callback; } xhr.onreadystatechange = callback; // 绑定句柄,这里和传统的ajax写法没什么区别 } },
abort: function() { if ( callback ) { callback(0,1); // 1表示调用callback时,isAbort为true,在callback执行过程中能区分出是响应完成还是取消导致的调用 } } }; } }); } |
15.4.2 前置过滤器和请求分发器的执行过程
prefilters中的前置过滤器在请求发送之前、设置请求参数的过程中被调用,调用prefilters的是函数inspectPrefiltersOrTransports;巧妙的时,transports中的请求分发器在大部分参数设置完成后,也通过函数inspectPrefiltersOrTransports取到与请求类型匹配的请求分发器:
// some code...
// Apply prefilters // 应用前置过滤器,参数说明: inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
// If request was aborted inside a prefiler, stop there // 如果请求已经结束,直接返回 if ( state === 2 ) { return false; }
// some code... // 注意:从这里开始要发送了
// Get transport // 请求分发器 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
// some code... |
函数inspectPrefiltersOrTransports从prefilters或transports中取到与数据类型匹配的函数数组,然后遍历执行,看看它的实现:
// Base inspection function for prefilters and transports // 执行前置过滤器或获取请求分发器 function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR, dataType /* internal */, inspected /* internal */ ) {
dataType = dataType || options.dataTypes[ 0 ]; inspected = inspected || {};
inspected[ dataType ] = true;
var list = structure[ dataType ], i = 0, length = list ? list.length : 0, executeOnly = ( structure === prefilters ), selection;
for(; i < length && ( executeOnly || !selection ); i++ ) { selection = list[ i ]( options, originalOptions, jqXHR ); // 遍历执行 // If we got redirected to another dataType // we try there if executing only and not done already if ( typeof selection === "string" ) { if ( !executeOnly || inspected[ selection ] ) { selection = undefined; } else { options.dataTypes.unshift( selection ); selection = inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR, selection, inspected ); } } } // If we're only executing or nothing was selected // we try the catchall dataType if not done already if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) { selection = inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR, "*", inspected ); } // unnecessary when only executing (prefilters) // but it'll be ignored by the caller in that case return selection; } |
15.4.3 总结
通过前面的源码解析,可以将前置过滤器和请求分发器总结如下:
前置过滤器 jQuery.ajaxPrefilter,prefilters
属性 |
值 |
功能 |
* |
undefined |
不做任何处理,事实上也没有*属性 |
json |
[ function ] |
被当作*处理 |
jsonp |
[ function ] |
修正url或data,增加回调函数名 在window上注册回调函数 注册script>json数据转换器 (被当作script处理) |
script |
[ function ] |
设置设置以下参数: 是否缓存 cache、(如果跨域)请求类型 、(如果跨域)是否触发AJAX全局事件 |
请求分发器 jQuery.ajaxTransport,transports
属性 |
值 |
功能 |
* |
[ function ] |
返回xhr分发器,分发器带有send、abort方法 send方法依次调用XMLHTTPRequest的open、send方法,向服务端发送请求,并绑定onreadystatechange事件句柄 |
script |
[ function ] |
返回script分发器,分发器带有send、abort方法 send方法通过在header中创建script标签异步载入js,并在script元素上绑定onload、script.onreadystatechange事件句柄 |
- _原创__jQuery源码分析-15AJAX-前置过滤器和请求分发器.pdf (411.5 KB)
- 下载次数: 77
评论
// Clean-up function jqXHR.always(function() { // Set callback back to previous value // 将备份的previous函数恢复 window[ jsonpCallback ] = previous; // Call if it was a function and we have a response // 响应完成时调用jsonp回调函数,问题是这个函数不是自动执行的么? if ( responseContainer && jQuery.isFunction( previous ) ) { window[ jsonpCallback ]( responseContainer[ 0 ] ); // 为什么要再次执行previous呢? } });
jqXHR.always的实现是说,不管当前这次的ajax请求是否成功,都要执行这个function,然后,如果是执行失败的话,而response数组里面又有内容的话,就用上一次的callback来执行一次,可能是某些优化的原因吧=.=....
分析还没看完,只是想法
发表评论
-
[原创] jQuery源码分析-04 选择器-Sizzle-设计思路
2011-11-14 20:59 6878作者:nuysoft/高云 QQ:47214707 Em ... -
[原创] jQuery源码分析-04 选择器-Sizzle-工作原理
2011-11-13 23:45 7915作者:nuysoft/高云 QQ:47214707 EM ... -
[原创] jQuery源码分析-02正则表达式-RegExp-常用正则表达式
2011-10-27 01:29 46680作者:nuysoft/JS攻城师/ ... -
[原创] jQuery源码分析-jQuery中的循环技巧
2011-10-27 00:36 14578作者:nuysoft/JS攻城师/高云 QQ:47214707 ... -
[原创] jQuery源码分析-10事件处理-Event-DOM-ready
2011-10-20 01:20 10631作者:nuysoft/JS攻城师/ ... -
[原创] jQuery源码分析-Java工程师应该向jQuery学习的8点建议
2011-10-18 23:56 12279作者:nuysoft/高云 QQ:47214707 EM ... -
[原创] jQuery源码分析-10事件处理-Event-事件绑定与删除-bind/unbind+live/die+delegat/undelegate
2011-10-18 22:31 15700作者:nuysoft/高云 QQ:47214707 EM ... -
[原创] jQuery源码分析-10事件处理-Event-源码结构
2011-10-17 01:01 12151作者:nuysoft/高云 QQ:47214707 EMail ... -
[原创] jQuery源码分析-07数据缓存-Cache
2011-10-13 19:55 12173作者:nuysoft/高云 QQ:47214707 EMail ... -
[原创] jQuery源码分析-06浏览器测试-Support
2011-10-13 19:19 9955作者:nuysoft/高云 QQ:47214707 EMail ... -
[原创] jQuery源码分析系列目录(持续更新)
2011-10-12 12:30 29404作者:nuysoft/高云 QQ:47214707 E ... -
[原创] jQuery源码分析-10事件处理-Event-概述和基础知识
2011-10-12 00:16 12043作者:nuysoft/高云 Q ... -
[原创] jQuery源码分析-08队列 Queue
2011-10-10 23:48 10838作者:nuysoft/高云 Q ... -
[原创] jQuery源码分析-03构造jQuery对象-工具函数
2011-09-29 23:21 29822作者:nuysoft/高云 QQ:47214707 E ... -
[原创] jQuery源码分析-15AJAX-类型转换器
2011-09-29 02:25 7446作者:nuysoft/高云 QQ:47214707 EM ... -
[原创] jQuery源码分析-03构造jQuery对象-源码结构和核心函数
2011-09-28 02:20 53017作者:nuysoft/高云 QQ:47214707 EMail ... -
[原创] jQuery源码分析-如何做jQuery源码分析
2011-09-27 00:22 15029近期在ITEYE陆续写了几篇jQuery源码分析,乐在其 ... -
[原创] jQuery源码分析-17尺寸和大小 Dimensions & Offset
2011-09-25 22:05 7077边读边写,不正确的地方,还请各位告诉我,多多交流共同学习, ... -
[原创] jQuery源码分析-00前言开光
2011-09-21 23:42 47041jQuery源码分析 - 前言 jQuery凭借简洁的语法和 ... -
[原创] jQuery源码分析-01总体架构
2011-09-21 23:31 751661. 总体架构 1.1 自调用匿名函 ...
相关推荐
jQuery源码分析-插件
6. **兼容性**:jQuery Unobtrusive Ajax与jQuery库无缝集成,因此可以利用jQuery提供的各种便利函数和选择器。 使用jQuery Unobtrusive Ajax,开发者可以快速地构建动态、响应式的Web应用,提供更好的用户体验。...
在Web开发中,jQuery是一个非常流行的JavaScript库,它极大地简化了DOM操作、事件处理以及Ajax交互。本主题聚焦于jQuery中的Ajax功能,特别是如何利用它进行异步用户名验证。Ajax,即Asynchronous JavaScript and ...
jQuery源码分析-初步
jQuery源码分析-事件(1).
jQuery源码分析-魔术方法
Ajax.BeginForm 提交,需要引用此文件才会执行OnSuccess
jQuery源码分析-事件(2).
基于 jsp + servlet + jquery + easy-ui + ajax 的学生成绩管理系统 基于 jsp + servlet + jquery + easy-ui + ajax 的学生成绩管理系统 基于 jsp + servlet + jquery + easy-ui + ajax 的学生成绩管理系统 基于 jsp...
jQuery 插件利用 Ajax(异步 JavaScript 和 XML)技术,可以实现在用户输入时动态搜索并显示结果,极大地提高了用户的交互体验。本篇文章将深入探讨 jQuery 的 Ajax 搜索功能及其核心实现。 ### 一、Ajax 基础 ...
文件列表中的"jquery-1.4.2.js"和"jquery-1.4.2.min.js"分别是未压缩和压缩版的jQuery 1.4.2,是jQuery UI运行的基础。"jquery-1.4.2-vsdoc.js"是一个用于Visual Studio的文档文件,为开发者提供IDE内的API提示。 ...
标题“PHP-JQuery-Ajax-json”揭示了这个压缩包文件主要涉及的是Web开发中的核心技术,具体包括PHP、jQuery、Ajax以及JSON。这四个元素在构建动态、交互式的Web应用程序时起着至关重要的作用。 1. **PHP(Hypertext...
jQuery源码分析 00 前言开光 01 总体架构 03 构造jQuery对象-源码结构和核心函数 03 构造jQuery对象-工具函数 05 异步队列 Deferred 08 队列 Queue 09 属性操作 ...15 AJAX-前置过滤器和请求分发器
- **前置过滤器和请求分发器**:解释jQuery如何通过预处理器和传输处理器来增强AJAX请求的功能,包括错误处理和数据格式转换。 - **类型转换器**:探讨jQuery中的类型转换机制,即如何将服务器返回的不同格式的数据...
通过以上知识点,我们可以看出 `jquery.editable-select` 是一个强大且灵活的工具,能够显著提升用户在选择操作中的体验,尤其适合需要动态过滤和自定义输入的场景。正确地理解和运用这些知识点,将使你在实际项目中...
这个压缩包包含两个关键文件:`jquery-ui-1.8.16.custom.min.js` 和 `jquery-ui-1.8.16.custom.css`,这些都是jQuery UI的特定版本,即1.8.16。这个版本在当时是一个广泛使用的稳定版本,提供了丰富的功能和组件。 ...
<script src="./public/js/jquery-ui-1.10.3.min.js"> <script src="./public/js/jquery.datepicker-zh-CN.js"></script> <link href="./public/css/jqueryui/jquery-ui-1.10.3.min.css" rel="stylesheet"> $( "#...
jquery插件jquery-ui-timepicker-addon.j