简介:
我们知道,ajax用于数据交互,但它不能跨域,跨域是指从一个域名的网页去请求另一个域名的资源。比如从 页面去请求 的资源。跨域的严格一点的定义是:只要 协议,域名,端口有任何一个的不同,就被当作是跨域。也就是说如果一家公司的官网有了改革,以前的官网网址和新的都可以访问,由于域名有稍微的改变,那么自己公司的官网就不能跳转到自己的另一个官网信息,这显然是很不方便的,于是jsonp就出场了,由它来解决这个问题。今天笔者从一个项目出发,来分析jsonp的具体用法。
webqq项目:
我们先来布局下注册登录页面:
用户名: 密 码:
加上样式
*{ margin:0; padding:0; list-style:none; font-family: "微软雅黑","张海山锐线体简"}body{ text-align:center;}#login_box{ width:300px; padding:10px; border:1px solid #000; margin:100px auto;}
然后封装好一个json函数,这个函数中,url,data,success,error,cbKey,timeout这六个参数是可选项,url就是就是公司给你的那个php地址,data就是我们之后要的用户名,密码,头像等等等等数据;sucsess函数就是当我们jsonp请求成功,会调用的函数;error就是jsonp请求失败要调用的函数;cbKey代表回调回调函数;timeout做延迟用的,如果在指定的延迟时间内没有完成相应的指令,服务器就会告诉网页就不要在等了,直接调用加载错误的那个函数吧!而这些参数有时全用的到,有时只用到部分,于是我们用参数options来代表它们,以便使用。
我们有关jsonp的代码都放在function json(opations){}中,在这个函数里,我们先整理好options:
options = options||{};if(!options.url) return;options.data=options.data||{};options.success=options.success||null;options.error=options.error||null;options.cbKey=options.cbKey||'cb';options.timeout=options.timeout||0;
下面来一步步写这个写回调函数
首先,我们要先把必要的食材都准备好:
var cbValue = 'jsonp'+Math.random();
你们懂的,之所以加上Math这个方法,是为了保证函数名随机,以便每次刷新的函数都不同。
为了防止因这个回调函数的函数名出现.而引发错误,我们用过replace将它替代掉,就是看到.就把它去掉
options.data[options.cbKey]=cbValue.replace('.','');
然后我们先做好这个函数,已备后来调用
window[options.data[options.cbKey]]=function(json){ clearInterval(timer); options.success && options.success(json); document.getElementsByTagName('head')[0].removeChild(oScript); window[options.data[options.cbKey]]=null; };
这是jsonp请求成功要调用的函数,为了保持每次刷新后的script引用都不一样及性能优化,我们要删掉script标签,即把不用的标签拿掉,src前脚链入,后脚拿掉,但是如果这个间隔里出现了状况,比如中间网断了不就挂了,于是我们需src成功时再拿掉,要在函数调用后再删掉。
然后要做url的相关处理了:
var arr=[];for(var key in options.data){ arr.push(key+'='+encodeURIComponent(options.data[key])); } options.url = options.url+'?'+arr.join('&')
先声明个空数组,然后通过encodeURIComponent把字符串作为URI 组件进行编码,把编码后的push进准备好的空数组里,最后把这个数组再用&把各段分开变成字符串。这里的知识点就是数据类型转换。
var oScript=document.createElement('script'); oScript.src=options.url; document.getElementsByTagName('head')[0].appendChild(oScript);
这一步就是创建script标签,并把它放入页面,知识点就是DOM操作。
if(options.timeout){ var timer=setTimeout(function(){ options.error&& options.error(); window[options.data[options.cbKey]]=function(){ }; },options.timeout); }
这是延迟后调用的error函数。
至此我们的jsonp函数就封装完毕了!!
关于cookie
下面我们开聊聊cookie,他的主要作用是保存信息,用来登录时记住用户名等,两个页面传数据,
主要的特点:①不能跨域,
②存储空间很小,4k左右
③一个域名只有一套cookie
④不安全,所以不要存隐私哦
⑤有效期过后,隐私无法保证
当然cookie的特点不止这些,由于本重点在jsonp上,因此关于cookie笔者只在此粗略的介绍,有时间一定再做更为细致的研究,现在把关于coookie的封装函数直接附上:
function removeCookie(name){ setCookie(name,'',-1);}function getCookie(name){ //alert(document.cookie); var arr=document.cookie.split('; '); for(var i=0;i
下面我们来直接在我们之前页面布局的那个html文档里来对这个登录页面进行编辑吧:
首先引入jsonp函数,我们把它存在一个jsonp.js的文件里吧,然后再引入有关cookie的函数,我们把这个存cookie的文件取名cookie.js,引入的代码如下:
然后我们开始核心的javascript操作吧
抓取对象:
var oReg=document.getElementById('reg');var oLogin=document.getElementById('login');var oUser=document.getElementById('user');var oPass=document.getElementById('pass');
下面是url地址,大家根据公司给的php接口链入就可以了
下面是注册的编辑,达到预期的效果就是当用户名和密码输入后点击注册,如果这个用户名未被注册过,就弹出注册成功,然后点击登录,就可进入聊天界面;如果这个用户名被注册过,则弹出用户名已备占用,然后重复上面操作,下面来用javascript实现
注册部分:
这时候要找公司给的相应的的注册部分的接口,形如:?a=reg&user=用户名&pass=密码&face=头像ID&cb=xxx
代码演示如下:
oReg.οnclick=function(){ //?a=reg&user=用户名&pass=密码&face=头像ID&cb=xxx jsonp({ url: url, data: { a: 'reg', user:oUser.value, pass:oPass.value, face:1+Math.random()*(8-1) }, success:function(json){ //{err: 0, msg: "注册成功"} alert(json.msg); if(json.err==0){ alert(json.msg); }else{ alert(json.msg); } } }); };
登录部分的代码演示如下:
oLogin.οnclick=function(){ //?a=lgn&user=用户名&pass=密码&cb=xxx jsonp({ url: url, data: { a: 'lgn', user: oUser.value, pass: oPass.value }, success:function(json){ // {err: 0, msg: "登录成功", face: 头像ID, login_time: 上次登录时间, token: "token"} if(json.err==0){ //跳转页面 //alert(json.token);//{13666022-D398-D647-70E2-2C247768EF04} setCookie('token',json.token,1);//存cookie setCookie('username',oUser.value,1);//存cookie window.location.href='chart.html' } } }); };
至此,注册登录的页面已经完工!
当输入正确的用户名和密码后,点击登录,就进入了聊天页面,下面开始聊天页面的的编辑。
首先先写好布局:
然后是给它加上样式:
*{ margin:0; padding:0; list-style:none; font-family: "微软雅黑","张海山锐线体简"}#div1{ position: absolute;width:100%; height:99%;}#left{ position:absolute;left:0;top:0;width:79%; height:100%; -background:yellow;}#content{ position:absolute;left:0;top:0;width:100%; height:79%; -background:pink;overflow-x:hidden;overflow-y:auto;}#content dl{ border-bottom:1px dashed #999; margin-bottom:0.2em;}#content dl dt span{ font-size: 16px; font-weight:bold;}#content dl dt strong{ font-weight:normal; font-size:12px;color:#999;}#content dl dd{ padding-left:2em;font-size: 14px;}#input_box{ position:absolute;left:0;bottom:0;width:100%; height:20%; background:#ccc;border-top:10px solid #000;}#input_box textarea{ width:100%; height:100%; border:none; resize:none;}#exit{ position:absolute;right:5%; top:5%; padding:10px; font-weight:bold; z-index:99999999;}#btn_send{ position:absolute;right:5%; bottom:30%; padding:10px; font-weight:bold;}#right{ position:absolute;right:0;top:0;width:20%; height:100%; border-left:10px solid #000; background:green; overflow-x:hidden;overflow-y:auto;}#right li{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap;margin: 2px; background: #eee;padding:5px;}/* 文字超出显示省略号*/#right li img{ width:40px;vertical-align:middle;margin-right:20px;}
和编辑注册登录页面一样加入jsonp和cookie对应的js文件:
核心javascript部分编,每次的jsonp调用时,要参照公司给的相关接口,根据接口来写,具体编辑如下:
先抓取对象:
var oBtnSend=document.getElementById('btn_send');var oTxt=document.getElementById('txt1');var oContent=document.getElementById('content');var oRight=document.getElementById('right');var oExit=document.getElementById('exit'); var url='http://zhinengshe.com/exercise/im/api.php'; var toKenContent=getCookie('token');var username=getCookie('username');
然后写发言部分:
oBtnSend.οnclick=function(){ //?a=snd_msg&content=内容&token=&cb=xxx jsonp({ url: url, data: { a: 'snd_msg', content: oTxt.value, token: toKenContent //取cookie }, success:function(json){ //{err: 0, time: 发布时间, ID: 消息ID} json.content=oTxt.value; json.username=username; //取cookie //{err: 0, time: 发布时间, ID: 消息ID,content:xxx,username:xxx} createDl(json); oTxt.value=''; } }) };
jsonp({ url: url, data: { a: 'get_msg', token: toKenContent }, success:function(json){ // {err: 0, data: [{ID: 消息ID, post_time: 消息时间,content: 消息内容,username: 发言用户},...]} if(json.err==0){ var arr=json.data; for(var i=0;i
获取用户列表:
jsonp({ url: url, data: { a: 'get_user_list', token: toKenContent }, success:function(json){ //{err: 0, data: [{ID: 用户ID,username: 用户名,face: 用户头像}]} if(json.err==0){ var arr=json.data; for(var i=0;i8) arr[i].face=8; oLi.innerHTML=' '+arr[i].username; oRight.appendChild(oLi); } } } });
下面是注销:
//?a=logout&token=&cb=xxx oExit.οnclick=function(){ jsonp({ url: url, data: { a: 'logout', token: toKenContent, }, success:function(json){ //{err: 0, msg: "成功退出登录"} if(json.err==0){ window.location.href='login.html'; }else{ alert('网断了') } } }); };
获取更新:
//?a=get_msg_n&n=消息ID&token=&cb=xxx var lastId=0; setInterval(updatMsg,1000); function updatMsg(){ //console.log('请求:',lastId); jsonp({ url: url, data: { a: 'get_msg_n', n: lastId,//请求新信息的起始点 token:toKenContent }, success:function(json){ //{err: 0, data: [{ID:'1',post_time:'1364873875',content:'asdfsdf',face:'1',username:'test',to:'发给谁'},...]} if(json.err==0){ var arr=json.data; for(var i=0;i
function createDl(json){ //{err: 0, time: 发布时间, ID: 消息ID,content:xxx,username:xxx}发言后返回的数据 //{ID: 消息ID, post_time: 消息时间,content: 消息内容,username: 发言用户}获取所有信息返回的 //{ID:'101',post_time:'1364873875',content:'asdfsdf',face:'1',username:'test',to:'发给谁'}实时更新返回的 lastId=json.ID; //console.log('更新:',lastId) //整理返回的时间 var time=json.time||json.post_time; var oDl=document.createElement('dl'); var d=new Date(); d.setTime(time*1000) oDl.innerHTML= '
到这里聊天的界面就完工了!
以上就是我分享的内容,有欠妥的地方,敬请指正。