绑定事件
$("#id").bind("click",function(){})
解除绑定
$("#id").unbind("click",function(){})
让事件只执行一次 $("#id").one("click",function(){})
合成事件hover toggle
hover(enterfn,leavefn) 当鼠标放上时执行enterfn,当鼠标离开时执行leavefn 封装mouseover,mouseout
toggle(fn1,fn2) 当鼠标第一次点击时执行fn1,第二次点击执行fn2,以后依次执行 封装click
事件冒泡
mouseover、mouseenter mouseover会事件冒泡,mouseenter不会
mouseout、mouseleavemouseleave会阻止事件冒泡
阻止事件冒泡
$("#d1").click(function(e){ e.stopPropagation();})
事件参数
pageX、pageY、target 获得触发事件的元素(事件冒泡的起始,和this不一样) 相当于event.srcElement
altKey、shiftKey、ctrlKey获得alt、shift、ctrl是否按下,为bool值。
当键盘按下 keyCode 键盘码、which ascii码
当鼠标按下的时候which可以获取鼠标左右键(1,3)
移除事件绑定:bind()方法即可移除元素上所有绑定的事件,如果unbind("click")则只移除click事件的绑定。bind:+=;unbind:-=
一次性事件:如果绑定的事件只想执行一次随后立即unbind可以使用one()方法进行事件绑定。
常用的方法
html() text() val() attr() css() removeAttr() addClass() removeClass() toggleClass() hasClass() val()
获取节点对象
next()方法用于获取节点之后的挨着的第一个兄弟元素,$(".menuitem").next("div")、nextAll()方法用于获取节点之后的所有兄弟元素,$(".menuitem").nextAll("div")
prev()、prevAll()兄弟中之前的元素。 siblings()方法用于获取所有同辈元素(前后都拿到),siblings、next等所有能传递选择器的地方能够使用的语法都和$()语法一样。$(".menuitem").siblings("li")。
直接把元素移动过去,并且包含所有事件
prepend
prependTo
在开始标签之后添加元素 加子节点
after
afterTo
在结束标签外添加元素 加兄弟节点
before
beforeTo
在开始标签前添加元素 加兄弟节点
删除节点
remove() 删除当前节点
empty() 清空当前节点之间的内容,节点保留
替换节点:
$("br").replaceWith("<hr/>"),将<br/>替换为<hr/>
包裹节点
wrap()将所有元素逐个用指定标签包裹,$("b").wrap("<fontcolor='red'></font>") 将所有粗体字红色显示
动画
show()、hide()
toggle() 切换显示隐藏
slideDown、slideUp、 fadeOut、fadeIn
复杂动画
animate({ left: 0, top: 0, width: 300,height: 300 })、.animate({opacity: 0 }).animate({ opacity: 1 })。还可以指定增量,$(“#div1”).animate({height: “+=100” }); //如果是+=、-=等增量形式要写成字符串,因为JavaScript不认识这种语法
链式编程
$(this).css("background-color", "red").siblings().css("background-color", "white");
案例:选中的p变色 $(this).css();$(this).siblings().css()
案例:评分控件。prevAll,this,nextAll
重申问题,不要$().click=function;好多时候能.出来;不要在引用js的代码里再写代码。
$.map(array,fn):
用来将一个数组,转成另一个数组。
对数组array中每个元素调用fn函数逐个进行处理,fn函数将处理返回,最后得到一个新数组。
例子:得到一个元素值是原数组值二倍的新数组
回调函数:自己定义,系统调用。(你赚的钱,由你老婆负责花—注:你自己不能花)
var arr = [3, 5, 9];
var arr2 = $.map(arr, function(item) { return item * 2; });//联想C#委托的例子。函数式编程。
$.map不能处理Dictionary风格的数组(jason)。
$.each(array,fn):
对数组arry每个元素调用fn函数进行处理,没有返回值。
var arr = { "tom": "汤姆", "jerry": "杰瑞", "lily": "莉莉" };//json格式的对象(dict)
$.each(arr, function(key, value) { alert(key+"="+value); });
如果是普通风格的数组,则key的值是序号。
还可以省略function的参数,这时候用this可以得到遍历的当前元素:
var arr = [3, 6, 9];
$.each(arr, function() { alert(this); });
普通数组推荐用无参,用dict风格的就用key、value。
hover(over,out) 一个模仿悬停事件(鼠标移动到一个对象上面及移出这个对象)的方法。
当鼠标移动到一个匹配的元素上面时,会触发指定的第一个函数。当鼠标移出这个元素时,会触发指定的第二个函数。而且,会伴随着对鼠标是否仍然处在特定元素中的检测
eg: $("td").hover(
function () {
$(this).addClass("hover");
},
function () {
$(this).removeClass("hover");
}
);
mouseover(fn) mouseover事件会在鼠标移入对象时触发。
mouseout(fn) mouseout事件在鼠标从元素上离开后会触发。
mouseup(fn) mouseup事件会在鼠标点击对象释放时
表单验证
$('form:input').blur(function(){
var regEmail = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/; //email验证
var regTxt=/^[\u4e00-\u9fa5\da-zA-Z\-\_]+$/; //非特殊字符验证
var regMoney=/^([0-9]{1,}\.[0-9]{1,2}|[0-9]{1,})$/; //金额验证(至多两位小数)
var regPattern = / ^ [`~!@#$^&*()=|{}':;',\\[\\].<>/?~!@#¥……&*()&;—|{}【】‘;:”“'。,、?] $/; //常见特殊字符
var regName = /^[a-zA-Z0-9_]{4,32}$/; //用户名验证 (4-32个英文大小写字母、下划线、数字)
if($(this).is('#email')){
if(!regEmail .test(this.value)){
}
}
}).keyup(function(){
$(this).triggerHandler("blur");
}).focus(function(
$(this).triggerHandler("blur");
))
表格隔行变色
CSS
.even{background:#FFF38F;}
.odd{background:#FFFFEE;}
$(function(){
$("tbody>tr:odd").addClass("odd");
$("tbody>tr:even").addClass("even");
$("tr:contains('王武')").addClass("odd");
//另外一种用法
$('tr').filter(":contains('李')").addClass('odd');
})
单选框控制表格高亮
$('tbdoy>tr').click(function(){
$(this).addClass('selected').siblings().removeClass('selected').end()
.find(':radio').attr('checked',true);
})
复选框控制表格行高亮
$('tbdoy>tr').click(function(){
if($(this).hasClass('selected')){
$(this).removeClass('selected').find(':checkbox').attr('checked',false);
}else{
$(this).addClass('selected').find(':checkbox').attr('checked',true);
}
}
三元运算----添加或移除selected类
var hasSelected=$(this).hasClass('selected');
$(this)[hasSelected?"removeClass":"addClass"]('selected');
表格展开关闭
<tbody>
<tr class='parent' id='row_01'><td>第一行</td></tr>
<tr class='child_row_01'><td>第一行子集</td></tr>
</tbody>
$('tr.parent').click(function(){
$(this).toggleClass("selected")//添加、删除高亮
.sibings('.clild_'+this.id).toggle();影藏、显示所谓的子行
})
遍历checkbox
var a="";
$('input[type="checkbox"][name="chk"]:checked').each(
function() {
a=a+"|"+$(this).val();
}
);
$('input[type="checkbox"][name="chk"]').each(
function() {
a=a+"|"+$(this).val();
}
);
JQuery操作checkbox、radio例:将多个选中的checkbox的值组装成一个字符串
<script type=text/javascript>
function addMem(){
//var followers = document.getElementsByName("followers");
var f_str = '0';
$("input[@name='followers']").each(function(){
if($(this).attr("checked")==true){
f_str += ","+$(this).attr("value");
}
})
alert(f_str);
}
</script>
=====================
例:取选中的radio的值
var gender = $('input[@name=gender][@checked]').val();
=====================
转别人的一些东西:
jquery判断checkbox是否被选中
在html的checkbox里,选中的话会有属性checked="checked"。
如果用一个checkbox被选中,alert这个checkbox的属性"checked"的值alert($"#xxx".attr("checked")),会打印出"true",而不是"checked"!
如果没被选中,打印出的是"undefined"。觉得很奇怪是吗?继续看下去~
不要尝试去做这样的判断:if($"#xxx".attr("checked")=="true")
因为这么做是错的,jQuery的API手册上写,attr(name)的返回值是object。
所以,应该是if($"#xxx".attr("checked")==true)
====================================
jquery全选/取消选择checkbox示例:
<input type="checkbox"Double click to hide line number.">
<script type="text/javascript">
<!--
$(function() {
$("#checkedAll").click(function() {
if ($(this).attr("checked") == true) { // 全选
$("input[@name='checkbox_name[]']").each(function() {
$(this).attr("checked", true);
});
} else { // 取消全选
$("input[@name='checkbox_name[]']").each(function() {
$(this).attr("checked", false);
});
}
});
});
//-->
</script>
=================================================
jquery radio取值,checkbox取值,select取值,radio选中,checkbox选中,select选中,及其相关获取一组radio被选中项的值
var item = $('input[@name=items][@checked]').val();
获取select被选中项的文本
var item = $("select[@name=items] option[@selected]").text();
select下拉框的第二个元素为当前选中值
$('#select_id')[0].selectedIndex = 1;
radio单选组的第二个元素为当前选中值
$('input[@name=items]').get(1).checked = true;
获取值:
文本框,文本区域:$("#txt").attr("value");
多选框checkbox:$("#checkbox_id").attr("value");
单选组radio: $("input[@type=radio][@checked]").val();
下拉框select: $('#sel').val();
控制表单元素:
文本框,文本区域:$("#txt").attr("value",'');//清空内容
$("#txt").attr("value",'11');//填充内容
多选框checkbox: $("#chk1").attr("checked",'');//不打勾
$("#chk2").attr("checked",true);//打勾
if($("#chk1").attr('checked')==undefined) //判断是否已经打勾
单选组radio: $("input[@type=radio]").attr("checked",'2');//设置value=2的项目为当前选中项
下拉框select: $("#sel").attr("value",'-sel3');//设置value=-sel3的项目为当前选中项
$("<option value='1'>1111</option><option value='2'>2222</option>").appendTo("#sel")//添加下拉框的option
$("#sel").empty();//清空下拉框
最下端滚轮加载事件
$(function () {
$(window).scroll(function () {
if (arrivedAtBottom()) {
var wid = $("#wid").val();
var index = $("#index").val();
var count = $("#count").val();
var load = '<tr class="re"><td><img src="images/3271623453203.gif" /></td><td class="td1"></td></tr>';
if (parseInt(index) * 100 < parseInt(count))
$.ajax({
type: "Post",
url: "ashx/LinksFangZhiS.ashx",
data: { "wid": wid, "index": parseInt(index) + 1 },
beforeSend: function () {
$(".listable").append(load);
},
complete: function () {
$("tr").remove(".re");
},
success: function (back) {
$(".listable").append(back);
$("#index").val(parseInt(index) + 1);
}
});
}
});
var arrivedAtBottom = function () {
return $(document).scrollTop() + $(window).height() == $(document).height();
}
});
网页选项卡切换
var $ div_li=$("div.tab_menu ul li");
$div_li.click(function(){
$(this).addClass("selected").siblings().removeClass("selected");
var index=$div_li.index(this);
$("div.tab_box>div").eq(index).show().sibings().hide();
}).hover(function(){
$(this).addClass("hover");
},function(){
$(this).removeClass("hover");
})
序列化与反序列化
serialize()、serializeArray()和param()
serialize()方法也是作用于一个JQuery对象,它能够将DOM元素内容序列化为字符串,用于ajax请求。通过使用serialize()方法,可以提交本页面的所有域,代码如下:
$("#send").click(function(){
$.get("get1.jsp", $("#form1").serialize(), function(data, textStatus)
$("#resText").html(data);
});
});
当单击“提交”按钮后,所有属于1gvddddform1的表单元素都能提交到后台,即使在表单中再增加字段,脚本仍然能够使用,并且不需要做其他多余工作。
用字符串方式时,需要注意对字符编码(中文问题),如果不希望编码带来麻烦,可以使用serialize()方法,它会自动编码。
因为serialize()方法作用于JQuery对象,所以不光只有表单能使用它,其他选择器选取的元素也都能使用它,如以下JQuery代码:
$(":checkbox,:radio").serialize();
把复选框和单选框的值序列化为字符串形式,只会将选中的值序列化。
在JQuery中还有一个与serialize()类似的方法--serializeArray(),该方法不是返回字符串,而是将DOM元素序列化后,返回JSON格式的数据。JQuery代码如下:
var fields = $(":checkbox,:radio").serializeArray();
console.log(fields); //用FireBug输出
$.param()方法是serialize()方法的核心,用来对一个数组或对象按照key/value进行序列化。
比如将一个普通的对象序列化:
var obj = {a:1,b:2,c:3};
var k = $.param(obj);
alert(k); //输出a=1&b=2&c=3
获取网站根路径(站点及虚拟目录),获得网站的根目录或虚拟目录的根地址
//js获取网站根路径(站点及虚拟目录),获得网站的根目录或虚拟目录的根地址
function getRootPath1() {
var strFullPath = window.document.location.href;
var strPath = window.document.location.pathname;
var pos = strFullPath.indexOf(strPath);
var prePath = strFullPath.substring(0, pos);
var postPath = strPath.substring(0, strPath.substr(1).indexOf('/') + 1);
return (prePath + postPath);
}
//js获取网站根路径(站点及虚拟目录),获得网站的根目录或虚拟目录的根地址
function getRootPath2() {
var pathName = window.location.pathname.substring(1);
var webName = pathName == '' ? '' : pathName.substring(0, pathName.indexOf('/'));
//return window.location.protocol + '//' + window.location.host + '/'+ webName + '/';
return window.location.protocol + '//' + window.location.host + '/' + webName;
}
【处理Json】
json字符串-单、双引号:
在js中, escape("'")=%27, escape('“‘)=%22;
string json = "{\"Id\":1,\"" + name.Replace("'",%27).Replace("\"",%22) + "\":\"jinho1\",\"Sex\":\"male\"}";
代码示例:
<script>
var UserList = [
{"UserID":11, "Name":{"FirstName":"Truly","LastName":"Zhu"}, "Email":"zhuleipro◎hotmail.com"},
{"UserID":12, "Name":{"FirstName":"Jeffrey","LastName":"Richter"}, "Email":"xxx◎xxx.com"},
{"UserID":13, "Name":{"FirstName":"Scott","LastName":"Gu"}, "Email":"xxx2◎xxx2.com"}
];
alert(UserList[0].Name.FirstName);
</script>
事实上除了使用"."引用属性外,我们还可以使用下面语句:
alert(UserList[0]["Name"]["FirstName"]); 或者 alert(UserList[0].Name["FirstName"]);
页面获取json对象:
var jsonArr = eval("(" + msg + ")");
alert(" UserID :" + jsonArr[0]. UserID );
alert(" Name :" + jsonArr[0]. Name );
var cateTemp = "";
json = eval(jsonArr[1]);
for (var perObj in json) {
cateTemp = cateTemp + "<li>" + perObj + "(<a>" + json[perObj] + "</a>)</li>";
//alert(cateTemp);
}
【异步 (表单序列化元素)】
$.ajax({
type:"get",
url:"test.json",
dataType:html/script/json/jsonp/text,
data:$("#form1").serialize(),
beforeSend:function(){
},
complete:function(){
},
success:function(data){
},
error:function(){
}
})
【JSONP】
快速应用示例:
flightHandler({
"code": "CA2013",
"price": 8888,
"tickets": 3
});
$.ajax({
type: "get",
async: false, url:"http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998",
dataType: "jsonp", jsonp:"callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback) jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
success: function(json){
alert('您查询到航班信息:票价: ' + json.price + ' 元,余票: ' + json.tickets + ' 张。');
},
error: function(){
alert('fail');
}
});
什么是JSON?
前面简单说了一下,JSON是一种基于文本的数据交换方式,或者叫做数据描述格式,你是否该选用他首先肯定要关注它所拥有的优点。
JSON的优点:
1、基于纯文本,跨平台传递极其简单;
2、Javascript原生支持,后台语言几乎全部支持;
3、轻量级数据格式,占用字符数量极少,特别适合互联网传递;
4、可读性较强,虽然比不上XML那么一目了然,但在合理的依次缩进之后还是很容易识别的;
5、容易编写和解析,当然前提是你要知道数据结构;
JSON的缺点当然也有,但在作者看来实在是无关紧要的东西,所以不再单独说明。
JSON的格式或者叫规则:
JSON能够以非常简单的方式来描述数据结构,XML能做的它都能做,因此在跨平台方面两者完全不分伯仲。
1、JSON只有两种数据类型描述符,大括号{}和方括号[],其余英文冒号:是映射符,英文逗号,是分隔符,英文双引号""是定义符。
2、大括号{}用来描述一组“不同类型的无序键值对集合”(每个键值对可以理解为OOP的属性描述),方括号[]用来描述一组“相同类型的有序数据集合”(可对应OOP的数组)。
3、上述两种集合中若有多个子项,则通过英文逗号,进行分隔。
4、键值对以英文冒号:进行分隔,并且建议键名都加上英文双引号"",以便于不同语言的解析。
5、JSON内部常用数据类型无非就是字符串、数字、布尔、日期、null 这么几个,字符串必须用双引号引起来,其余的都不用,日期类型比较特殊,这里就不展开讲述了,只是建议如果客户端没有按日期排序功能需求的话,那么把日期时间直接作为字符串传递就好,可以省去很多麻烦。
JSON实例:
// 描述一个人
var person = {
"Name": "Bob",
"Age": 32,
"Company": "IBM",
"Engineer": true
}
// 获取这个人的信息
var personAge = person.Age;
// 描述几个人
var members = [
{
"Name": "Bob",
"Age": 32,
"Company": "IBM",
"Engineer": true
},
{
"Name": "John",
"Age": 20,
"Company": "Oracle",
"Engineer": false
},
{
"Name": "Henry",
"Age": 45,
"Company": "Microsoft",
"Engineer": false
}
]
// 读取其中John的公司名称
var johnsCompany = members[1].Company;
// 描述一次会议
var conference = {
"Conference": "Future Marketing",
"Date": "2012-6-1",
"Address": "Beijing",
"Members":
[
{
"Name": "Bob",
"Age": 32,
"Company": "IBM",
"Engineer": true
},
{
"Name": "John",
"Age": 20,
"Company": "Oracle",
"Engineer": false
},
{
"Name": "Henry",
"Age": 45,
"Company": "Microsoft",
"Engineer": false
}
]
}
// 读取参会者Henry是否工程师
var henryIsAnEngineer = conference.Members[2].Engineer;
关于JSON,就说这么多,更多细节请在开发过程中查阅资料深入学习。
什么是JSONP?
先说说JSONP是怎么产生的:
其实网上关于JSONP的讲解有很多,但却千篇一律,而且云里雾里,对于很多刚接触的人来讲理解起来有些困难,小可不才,试着用自己的方式来阐释一下这个问题,看看是否有帮助。
1、一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面、动态网页、web服务、WCF,只要是跨域请求,一律不准;
2、不过我们又发现,Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有"src"这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>);
3、于是可以判断,当前阶段如果想通过纯web端(ActiveX控件、服务端代理、属于未来的HTML5之Websocket等方式不算)跨域访问数据就只有一种可能,那就是在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理;
4、恰巧我们已经知道有一种叫做JSON的纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据;
5、这样子解决方案就呼之欲出了,web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件(一般以JSON为后缀),显而易见,服务器之所以要动态生成JSON文件,目的就在于把客户端需要的数据装入进去。
6、客户端在对JSON文件调用成功之后,也就获得了自己所需的数据,剩下的就是按照自己需求进行处理和展现了,这种获取远程数据的方式看起来非常像AJAX,但其实并不一样。
7、为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。
如果对于callback参数如何使用还有些模糊的话,我们后面会有具体的实例来讲解。
JSONP的客户端具体实现:
不管jQuery也好,extjs也罢,又或者是其他支持jsonp的框架,他们幕后所做的工作都是一样的,下面我来循序渐进的说明一下jsonp在客户端的实现:
1、我们知道,哪怕跨域js文件中的代码(当然指符合web脚本安全策略的),web页面也是可以无条件执行的。
远程服务器remoteserver.com根目录下有个remote.js文件代码如下:
alert('我是远程文件');
本地服务器localserver.com下有个jsonp.html页面代码如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
</head>
<body>
</body>
</html>
毫无疑问,页面将会弹出一个提示窗体,显示跨域调用成功。
2、现在我们在jsonp.html页面定义一个函数,然后在远程remote.js中传入数据进行调用。
jsonp.html页面代码如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
var localHandler = function(data){
alert('我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:' + data.result);
};
</script>
<script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
</head>
<body>
</body>
</html>
remote.js文件代码如下:
localHandler({"result":"我是远程js带来的数据"});
运行之后查看结果,页面成功弹出提示窗口,显示本地函数被跨域的远程js调用成功,并且还接收到了远程js带来的数据。很欣喜,跨域远程获取数据的目的基本实现了,但是又一个问题出现了,我怎么让远程js知道它应该调用的本地函数叫什么名字呢?毕竟是jsonp的服务者都要面对很多服务对象,而这些服务对象各自的本地函数都不相同啊?我们接着往下看。
3、聪明的开发者很容易想到,只要服务端提供的js脚本是动态生成的就行了呗,这样调用者可以传一个参数过去告诉服务端“我想要一段调用XXX函数的js代码,请你返回给我”,于是服务器就可以按照客户端的需求来生成js脚本并响应了。
看jsonp.html页面的代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
// 得到航班信息查询结果后的回调函数
var flightHandler = function(data){
alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。');
};
// 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";
// 创建script标签,设置其属性
var script = document.createElement('script');
script.setAttribute('src', url);
// 把script标签加入head,此时调用开始
document.getElementsByTagName('head')[0].appendChild(script);
</script>
</head>
<body>
</body>
</html>
这次的代码变化比较大,不再直接把远程js文件写死,而是编码实现动态查询,而这也正是jsonp客户端实现的核心部分,本例中的重点也就在于如何完成jsonp调用的全过程。
我们看到调用的url中传递了一个code参数,告诉服务器我要查的是CA1998次航班的信息,而callback参数则告诉服务器,我的本地回调函数叫做flightHandler,所以请把查询结果传入这个函数中进行调用。
OK,服务器很聪明,这个叫做flightResult.aspx的页面生成了一段这样的代码提供给jsonp.html(服务端的实现这里就不演示了,与你选用的语言无关,说到底就是拼接字符串):
flightHandler({
"code": "CA1998",
"price": 1780,
"tickets": 5
});
我们看到,传递给flightHandler函数的是一个json,它描述了航班的基本信息。运行一下页面,成功弹出提示窗口,jsonp的执行全过程顺利完成!
4、到这里为止的话,相信你已经能够理解jsonp的客户端实现原理了吧?剩下的就是如何把代码封装一下,以便于与用户界面交互,从而实现多次和重复调用。
什么?你用的是jQuery,想知道jQuery如何实现jsonp调用?好吧,那我就好人做到底,再给你一段jQuery使用jsonp的代码(我们依然沿用上面那个航班信息查询的例子,假定返回jsonp结果不变):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Untitled Page</title>
<script type="text/javascript" src=jquery.min.js"></script>
<script type="text/javascript">
jQuery(document).ready(function(){
$.ajax({
type: "get",
async: false,
url: "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998",
dataType: "jsonp",
jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
success: function(json){
alert('您查询到航班信息:票价: ' + json.price + ' 元,余票: ' + json.tickets + ' 张。');
},
error: function(){
alert('fail');
}
});
});
</script>
</head>
<body>
</body>
</html>
是不是有点奇怪?为什么我这次没有写flightHandler这个函数呢?而且竟然也运行成功了!哈哈,这就是jQuery的功劳了,jquery在处理jsonp类型的ajax时(还是忍不住吐槽,虽然jquery也把jsonp归入了ajax,但其实它们真的不是一回事儿),自动帮你生成回调函数并把数据取出来供success属性方法来调用,是不是很爽呀?
这里针对ajax与jsonp的异同再做一些补充说明:
1、ajax和jsonp这两种技术在调用方式上“看起来”很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装;
2、但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本。
3、所以说,其实ajax与jsonp的区别不在于是否跨域,ajax通过服务端代理一样可以实现跨域,jsonp本身也不排斥同域的数据的获取。
4、还有就是,jsonp是一种方式或者说非强制性协议,如同ajax一样,它也不一定非要用json格式来传递数据,如果你愿意,字符串都行,只不过这样不利于用jsonp提供公开服务。
总而言之,jsonp不是ajax的一个特例,哪怕jquery等巨头把jsonp封装进了ajax,也不能改变着一点!
$(function () {
$("#DK").live("click", function () {
});
$("[name='Sel']").bind("change", function () {
html = AnalysisXML('xml/Data/metadata.xml');
});
function AnalysisDeepXML(xml) {
$.get(xml, function (d) {
var html = '<ul id="browser" class="filetree">';
var temp = "";
$(d).find('nodeP').each(function () {
var $parentNode = $(this);
var parentName = $parentNode.find('name').first().text();
parentName = parentName.substring(0, parentName.lastIndexOf('('));
var parentId = $parentNode.find('id').first().text();
html += '<li><span title="' + parentId + '" class="folder">' + parentName + '</span>';
var $children = $parentNode.find('children').first();
if ($children != undefined) {
html += '<ul>';
$children.find('node').each(function () {
var $childrenNode = $(this);
var childrenName = $childrenNode.find('name').first().text();
var childrenNum = childrenName.substring(childrenName.lastIndexOf('(') + 1, childrenName.lastIndexOf(')'));
childrenName = childrenName.substring(0, childrenName.lastIndexOf('('));
var childrenId = $childrenNode.find('id').first().text();
html += '<li><span class="file" title="' + childrenId + '">' + childrenName + '</span></li>';
});
html += '</ul>';
}
html += '</li>';
temp = html;
});
html += '</ul>';
return html;
});
}
//解析xml返回html 深入两层
//function AnalysisDeepXML(xml) {
// var html = '<ul id="browser" class="filetree">';
// var temp = "";
// $.get(xml, function (d) {
// $(d).find('nodeP').each(function () {
// var $parentNode = $(this);
// var parentName = $parentNode.find('name').first().text();
// parentName = parentName.substring(0, parentName.lastIndexOf('('));
// var parentId = $parentNode.find('id').first().text();
// html += '<li><span title="' + parentId + '" class="folder">' + parentName + '</span>';
// var $children = $parentNode.find('children').first();
// if ($children != undefined) {
// html += '<ul>';
// $children.find('node').each(function () {
// var $childrenNode = $(this);
// var childrenName = $childrenNode.find('name').first().text();
// var childrenNum = childrenName.substring(childrenName.lastIndexOf('(') + 1, childrenName.lastIndexOf(')'));
// childrenName = childrenName.substring(0, childrenName.lastIndexOf('('));
// var childrenId = $childrenNode.find('id').first().text();
// html += '<li><span class="file" title="' + childrenId + '">' + childrenName + '</span></li>';
// });
// html += '</ul>';
// }
// html += '</li>';
// temp = html;
// });
// });
// html += '</ul>';
// return html;
//}
//解析xml返回html 深入一层
function AnalysisXML(xml, term) {
var html = '<ul id="browser" class="filetree">';
$.get(xml, function (d) {
$(d).find('nodeP').each(function () {
var $parentNode = $(this);
if (term != "" || term != undefined) {
var name = $parentNode.attr('name');
if (name == term) {
var parentName = $parentNode.find('name').text();
parentName = parentName.substring(0, parentName.lastIndexOf('('));
var parentId = $parentNode.find('id').text();
html += '<li><span class="ico" title="' + parentId + '">' + parentName + '</span></li>';
}
} else {
var parentName = $parentNode.find('name').text();
parentName = parentName.substring(0, parentName.lastIndexOf('('));
var parentId = $parentNode.find('id').text();
html += '<li><span class="file" title="' + parentId + '">' + parentName + '</span></li>';
}
})
});
html += '</ul>';
return html;
}
index.html
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>无标题页</title>
<script src="jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){
$.ajax({url:"City.xml",
success:function(xml){
$(xml).find("province").each(function(){
var t = $(this).attr("name");//this->
$("#DropProvince").append("<option>"+t+"</option>");
});
}
});
$("#DropProvince").change(function(){
$("#sCity>option").remove();
var pname = $("#DropProvince").val();
$.ajax({url:"City.xml",
success:function(xml){
$(xml).find("province[name='"+pname+"']>city").each(function(){
$("#sCity").append("<option>"+$(this).text()+"</option>");
});
}
});
});
});
</script>
</head>
<body>
<form id="form1">
<div>
<select id="DropProvince" style="width:60px;">
<option>请选择</option>
</select>
<select id="sCity" style="width:60px;">
</select>
</div>
</form>
</body>
</html>
City.xml文件内容
City.xml
<?xml version="1.0" encoding="utf-8" ?>
<provinces>
<province name="湖北">
<city>武汉</city>
<city>黄石</city>
<city>宜昌</city>
<city>天门</city>
</province>
<province name="湖南">
<city>邵阳</city>
<city>长沙</city>
<city>岳阳</city>
</province>
<province name="广东">
<city>广州</city>
<city>深圳</city>
</province>
</provinces>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>无标题页</title>
<script src="jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){
$.ajax({url:"City.xml",
success:function(xml){
$(xml).find("province").each(function(){
var t = $(this).attr("name");//this->
$("#DropProvince").append("<option>"+t+"</option>");
});
}
});
$("#DropProvince").change(function(){
$("#sCity>option").remove();
var pname = $("#DropProvince").val();
$.ajax({url:"City.xml",
success:function(xml){
$(xml).find("province").each(function(){
var t = $(this).attr("name");
if ( t==pname ){
$(this).find("city").each(function(){
$("#sCity").append("<option>"+$(this).text()+"</option>");
});
}
});
}
});
});
});
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<select id="DropProvince" style="width:60px;">
<option>请选择</option>
</select>
<select id="sCity" style="width:60px;">
</select>
</div>
</form>
</body>
</html>