(37)只需要前端知识,就能理解的ajax教程
①新人学web前端时,遇见的第一个困难就是ajax
这里对于以下问题,不深入,只用 最简单的话 讲清楚什么是ajax,并且 让你会用ajax。
新人常见问题:
【1】到底什么是ajax?
【2】ajax时发生了什么事情?
【3】为什么ajax时要有url?
【4】为什么ajax时,有时候会有一个对象(object),有时候没有,有时候url后面有?或者&或者=或者其他什么?
【5】我怎么知道服务器(后端)返回什么内容?我如何处理?
②ajax是什么?
用通俗的话一步一步来解释:
【1】我决定去你家拜访,首先得知道你家在哪吧。你家的地址就是http的url;
【2】我到你家来做客,这是进行http访问(访问你家);
【3】你给我端茶倒水,这是你给我返回了一些资源,通常是一个网页(html);
【4】你在你家客厅摆放了一些吃的,并且我知道这些东西我可以吃。我知道可以吃,然后我就告诉你我想吃点东西,这是我再次发起请求;
【5】你让我不用动,然后给我拿了一点糕点过来。此时,我依然坐在你家的客厅沙发上,我只告诉你我要吃东西,你就给我了。
【4】和【5】这两步结合起来,这就是ajax;
ajax的实质是,在原有页面的基础上,发生某个js事件,然后执行了一个请求,服务器给予了一个回应。
如图:
如果说的再简单一点,就是我(网页)问服务器(后端)要东西,然后服务器给我了。
至于怎么要,下面说。
③ajax时发生了什么事情?
首先请看上图。
【1】触发某事件,实际上这里是指触发ajax事件。例如jquery里get请求事件:
$.get(URL,callback);
或者是一个post请求事件
$.post(URL,data,callback);
【2】发起请求后,就是执行以上事件。
这个事件必须的参数是URL,可选参数是data(get没有)和callback(回调函数,请求完成后执行的);
关键是URL
理解URL:
大部分新人之所以不明白ajax,主要是不明白这个url。
按照普通人的理解,url就是一个地址,比如一个文件a.txt他的url可以是C:\a.txt
当我访问c:\a.txt时,就访问的是这个文本文件。
这样理解当然也不算错误,但不全面。
按照我的解释,你可以把url理解为一个暗号,和服务器(后端)预先约定好的暗号。
注意,这里的url,通常指的是例如:
https://www.zhihu.com/topic/19626558/hot
中的
/topic/19626558/hot
为什么这么说呢?很简单。
你发送的url,事实上在后端看来,只是一个字符串,在未进行特殊处理的情况下,他并不能直接访问文件。
就比如上面我写的那个知乎的url,可能存在一个文件名是hot这样的文件么?显然并不可能。
事实上,不存在一个根目录下的topic文件夹,也不存在一个名为19626558的文件夹。
但为什么时候我们可以通过访问这个url来访问一个网页呢?事实上,是因为在http服务器进行处理过的了。
这里我简单的说一下其流程:
【1】我们前端和后端约定了一个url(暗号),这个暗号以'/topic'开头,但这个暗号表示什么意思呢?
【2】当后端遇见一个以这样暗号为开头的,他就知道,我是在访问一个话题类的页面,
但目前为止,后端还不知道话题是什么,自然也没法给我们返回内容;
如果我们不是以/topic为开头,而且以其他字符串为开头,自然也会有对应的代码来处理我们的请求(包括无效的字符串,也是有办法处理的)
【3】然后我们继续发送了下一部分'/19626558',这个实际上就是话题的id。
当后端获取到这个话题的id后,他会去数据库里进行查询。
如果这是一个有效的话题id,那么会返回给我们一大堆跟这个id相关的内容;
假如后端发现这个id是无效的,那么会告诉我们
注意这个页面是预制好的。
【5】然后后端会查看url(暗号)的下一部分'/hot '。服务器发现是'/hot',于是他按照热门程度,将内容排序好后返回给我们,避免我们看到的都是没人回复的帖子(那也太浪费感情了)。
如果下一部分是'/newest '呢,那就以时间发表顺序来返回内容给我们(毕竟有时候我们只想看看最新的);
那么假如什么都没有呢?是个空字符串的话,该怎么办?后端也有预先准备的办法,那就是默认给我们发送'/hot'的内容,并且将我们的url设置为'/hot'结尾的。
如果是其他结尾的,那么就可能返回一个404的页面(就像上面那样)
【6】按道理来说,讲解就到这里结束了。但是为了防止理解的过于片面,我假设一种情况。
比如说有一个调皮的程序员,他写了这么一段代码,假如你访问的url是一个/topic/19626558/joke(显然知乎并不会这么做),
那么他会将你转到一个小游戏的页面(他显然跟topic毫无关系,跟我们要访问的url也毫无关系)。
因此要搞清楚的是,url,只是我们约定好的一种形式,我通常会照着这个通俗的做法去做,但是我也可以任性的做些别的,比如/a/b/c页面却是/a/b页面的父页面(通俗做法显然是相反的);/a/b页面和/c页面是平级页面。
所以我说与其将url理解为一个地址,不如理解为一个暗号,一个你与后端程序员约定好的暗号。
你告诉他,当我说这个暗号的时候,我可能给你发送些什么东西(比如id,密码之类),你要给我返回些什么东西,比如一个页面、一个表格、一段动画这样。
④为什么要有url?
就像上面说的那样,他是一个暗号,你们必须有同样的暗号时,他才知道你想做什么;
例如/game时是想访问游戏页面,/news时是想访问新闻页面,/login是想登陆,/logout是想登出。
至于究竟是想访问页面呢,还是想登陆登出呢,或者是想获取一段数据呢?这要根据url(约定的暗号)来决定。
⑤为什么ajax时,有时候会有一个对象(object),有时候没有,有时候url后面有?或者&或者=或者其他什么?
这个问题事实上就涉及到了http请求的方法了。
我们通常用的http请求方法有两种,分别是get和post。
他们的区别简单的来说,就是一个会附带一个对象(post),另外一个是不带的(get)。
先说get和post的区别:
【1】get,如字面意思,请求,获取。
我(前端)告诉你(后端),我想获取什么东西(根据暗号事先约定好的),你当我说这个暗号(发送http请求)的时候,就返回给我;
【2】post,如字面意思,邮寄、发送。
假如我在玩游戏,我要下线/退出了,因此我要存档的对吧。你可以把存档这个行为,理解为post。我存档时,肯定要把我的经验、等级、装备、任务进度之类之类的内容,存到文件中去(在后端,一般是存到数据库之中);
但后端怎么知道我的这些数据呢?一般就是通过post了,例如我发送这样一个对象:
{lv:100, name:"水哥", exp:987654321,atk:12345, def:12345, gold:10000}
后端就会获取到这个对象,然后他就会把这个对象解析出来,存到数据库之中(比如MySQL)。
get一般在无敏感数据、数据量小的时候使用;
post一般在有敏感数据(比如密码),数据量大的时候使用;
因此,“为什么有时候会有这个对象”,这个问题就解释清楚啦。
另外一个,url里为什么有时候会有很长串的字符呢?
比如说:
/friend?id=123&online=true#abc
我将其分为三部分:
【1】问号以前的:/friend
【2】#号以前的:id=123&online=true
【3】#号以后的:abc
第一部分属于url,即我们约定的暗号,称为pathname
第二部分和第三部分都是请求部分,但他们有所区别:
仔细看第二部分,他们以&分隔,分别为id=123与online=true,这是典型的KV结构(即key和value)。而&符号通常表示and。因此我们可以将其理解为一个对象:{id:123,online:true} ——具体怎么转换是后端处理的事情,前端只需要这么理解就可以了。
第三部分是一个字符串abc,我们将其称为哈希地址。
他们有什么用呢?很简单。
【1】假设我在玩网页游戏,我需要获取在线的好友列表,因此以/friend开头,表示我要获取好友列表。
【2】假设我的id是123,因此我发送id=123(表示要找我的好友),但我的好友里面有在线的,也有非在线的,服务器怎么知道我要获取哪种呢?那么就通过检查online的值,发现其值为true,于是就知道我找的是在线好友了。
【3】另外还有一个哈希地址。我可以这么解释,我需要查看的是好友名称为abc的人的资料。因此,服务器返回的是一个在线的好友列表,以及好友名称为abc的人的全部资料。
(ps:具体怎么解释,全看约定)
⑥我怎么知道服务器(后端)返回什么内容?我如何处理?
还记不记得之前jquery的两个方法,他们都有一个回调函数?
这个回调函数的参数呢,就是返回的内容。
例如:
$.get('/abc', function(item){ //do something })
假设后端返回一个这样的对象:
{ id:1, name:"abc"}
那么回调函数的参数item的值,就是{ id:1,name:"abc"}
至于怎么知道的,想要深入的话可以去看源代码,只是了解ajax的话,知道这个事实就行了。
那么这个函数什么时候执行呢?
是在服务器返回内容之后,浏览器接受到的时候执行的。
Notes:
【1】假设我在0s的时候发送了这个get请求,
【2】在1s的时候,服务器接受到这个请求,他用了0.1s来处理,在1.1s的时候,给我返回以上那个对象;
【3】又过了0.5s,我接受到了这个返回对象(此时是1.6s),因此这个回调函数执行的时候,是在我发送get请求后1.6s执行的。
为什么要特别强调这个过程,原因在于:
当我们用ajax来给一个变量赋值时,我们不能在ajax外对赋值结束后的这个变量进行处理。
例如:
var id = null; $.get('/abc', function(item){ id = item.id; }) console.log(id);
你觉得console.log出来的id的值是什么?
答案:是null
原因在于,console.log(id)这段代码,在上面第【1】步执行结束后执行的。因此他的执行时间,实际上可能是第0.01s(第0s发送的get请求)
而等他获取值的时候,已经在第1.6s了,因此,第0.01时他的值是初始值(null)
这是新人很容易犯的一个错误,务必提醒自己,多多注意。
⑦补充:
对于ajax,纯前端是无法使用的,因为ajax的实质就是前后端交互,建议大家看一看我的Nodejs的博客,架设一个最简单的Nodejs服务器(非常容易),来进行一次简单的前后端交互,对于提高自己的ajax水平会有很大的帮助。