AJAX:”Asynchronous JavaScript and XML”
中文意思:异步JavaScript和XML。
指一种创建交互式网页应用的网页开发技术。
XmlHttpRequest对象
AJAX优点
Ajax在本质上是一个浏览器端的技术
Ajax技术之主要目的在于局部交换客户端及服务器间之数据
这个技术的主角XMLHttpRequest 的最主要特点,在于能够不用重新载入整个版面来更新资料,也就是所谓的Refresh without Reload(轻刷新)
与服务器之间的沟通,完全是透过Javascript 来实行
使用XMLHttpRequest 本身传送的数据量很小,所以反应会更快,也就让网络程式更像一个桌面应用程序
AJAX 就是运用Javascript 在后台悄悄帮你去跟服务器要资料,最后再由Javascript 或DOM 来帮你呈现结果,因为所有动作都是由Javascript 代劳,所以省去了网页重载的麻烦,使用者也感受不到等待的痛苦
异步请求基本步骤
使用XMLHttpRequest对象
按照下面模式,可以同步地XMLHttpRequest对象:
创建对象; - new (叫助手过来)
创建请求; - open (告诉他要去做的事情)
发送请求; - send (去吧)
readyState属性
readyState属性指出了XMLHttpRequest对象在发送/接收数据过程中所处的几个状态。XMLHttpRequest对象会经历5种不同的状态。
0:未初始化。new完后;
1:已打开。对象已经创建并初始化,但还未调用send方法
2:已发送。已经调用send 方法,但该对象正在等待状态码和头的返回;
3:正在接收。已经接收了部分数据,但还不能使用该对象的属性和方法,因为状态和响应头不完整;
4:已加载。所有数据接收完毕
XMLHttpRequest对象属性
一、onreadystatechange属性,设置回调函数。
二、readyState属性,获取当前XMLHttpRequest对象执行的状态:
1> 0表示以创建XMLHttpRequest对象,但是还没有初始化,即没有调用open()方法设置XMLHttpRequest对象。
2>1表示创建了XMLHttpRequest对象,并且调用了open()方法进行初始化,但是还没有调用send()方法。
3>3表示浏览器正在接受服务器的响应数据。
4>所有数据已经被接受完毕。
三、status属性,服务器返回的http状态码。(>=200 and <300、304未修改,读取缓存。都表示成功)
四、statusText属性,服务器返回的状态码对应的友好的文字说明,比如200对应的OK.
五、responseText属性,以字符串方式获取服务器对客户端的响应。
六、responseXml属性,当请求的是一个xml文件时,或者响应头中Content-Type为:text/xml或application/xml时,返回一个XmlDocument对象(Dom节点对象),支持标准的dom的成员,比如:childNodes、documentElement、firstChild、lastChild、nextSibling、nodeName、nodeType、nodeValue、parentNode、doctype等。
XMLHttpRequest对象常用方法
一、open(“get”,”url”,true)初始化,如果第三个参数为false,则js等待请求完毕后才会继续执行。
二、setRequestHeader(“”,””)增加http请求头信息。在open()之后,send()之前调用。
三、send(null);发送请求。send()方法的参数表示为在请求报文体中发送的数据内容。为了最大化的浏览器兼容问题,如果没有请求报文体就传递null。get请求没有请求报文体,所以一般为null。使用post请求时才需要设置报文体。
四、getResponseHeader(“Content-Type”),根据响应的报文头获得报文内容。
五、getAllResponseHeaders();获取所有的响应报文头内容。
六、abort();取消当前的http请求,取消之后如果要重新发起请求,建议重新创建一个XMLHttpRequest对象。
Ajax使用注意
- xhr只能向同一个域中的相同端口号、相同协议的url发起请求,不能跨域,否则会引起错误。
- 为了浏览器兼容,get请求时最好为send()传递null参数。
- 在创建了xhr对象后立刻设置onreadystatechange事件,这样就能监视到所有的状态。如果不需要监视其他状态只监视readyState==4的状态则可以在send()之前设置。
- get请求时,请求中的QueryString的参数名称与参数值最好使用encodeURIComponent()进行编码。否则在某些浏览器下无法获取该值,比如IE.
- post请求时,为了像表单那样提交数据需要设置请求的Content-Type为:application/x-www-form-urlencoded。send(“键=值&键=值”)
- 解析json格式时eval(“(“+json+”)”)。但有安全性问题
演示
cshtml:
1 | @{ |
controller:
1 | //get |
基于AjaxHelper的Ajax
MVC框架本身提供了AjaxHelper类用于Ajax异步请求,所以如果你想省事,就用这种方式吧~
AjaxHelper帮助器方法:
Helper method | Description |
---|---|
Ajax.ActionLink | Creates a hyperlink to a controller action that fires an Ajax request when clicked |
Ajax.RouteLink | Similar to Ajax.ActionLink, but generates a link to a particular route instead of a named controller action |
Ajax.BeginForm | Creates a form element that submits its data to a particular controller action using Ajax |
Ajax.BeginRouteForm | Similar to Ajax.BeginForm, but creates a form that sub- mits its data to a particular route instead of a named control- ler action |
Ajax.GlobalizationScript | Creates an HTML script element that references a script that contains culture information |
Ajax.JavaScriptStringEncode | Encodes a string to make sure that it can safely be used inside JavaScript |
上面的方法貌似很多,但是实际开发中用到的就两个帮助器方法而已:
Ajax.ActionLink()和Ajax.BeginForm()
这里有个问题:怎样让项目知道我们用的是MVC自带的Ajax呢?
导入js
A、在Web.config里边配置:
1 | <add key="UnobtrusiveJavaScriptEnabled" value="true" /> |
B、在页面中引用下面的js类库即可:
1 | @section scripts{ |
一般更为常见的是在布局页/Views/Shared/_Layout.cshtml 中引入,例如:
1 |
|
Ajax.ActionLink():
向客户端输出一个链接地址,当单击这个链接时可以Ajax调用Controller中的方法,Ajax.ActionLink()方法有许多重载,下面是其重载之一:
public static string ActionLink(this AjaxHelper ajaxHelper, string linkText, string actionName, object routeValues, AjaxOptions ajaxOptions);
linkText:是显示在客户端的文本
actionName:是Action的名字,默认情况下我们会使用当前的Controller。
routeValues:将传入到Controller中方法的参数
ajaxOptions:配置Ajax的一些选项
Confirm | 获取或设置提交请求之前,显示在确认窗口中的消息。 |
---|---|
HttpMethod | 获取或设置 HTTP 请求方法(“Get”或“Post”)。 |
InsertionMode | 获取或设置指定如何将响应插入目标 DOM 元素的模式。 |
LoadingElementId | 获取或设置加载 Ajax 函数时要显示的 HTML 元素的 id 特性。 |
OnBegin | 获取或设置更新页面之前,恰好调用的 JavaScript 函数的名称。 |
OnComplete | 获取或设置实例化响应数据之后但更新页面之前,要调用的 JavaScript 函数。 |
OnFailure | 获取或设置页面更新失败时,要调用的 JavaScript 函数。 |
OnSuccess | 获取或设置成功更新页面之后,要调用的 JavaScript 函数。 |
UpdateTargetId | 获取或设置要使用服务器响应来更新的 DOM 元素的 ID。 |
Url | 获取或设置要向其发送请求的 URL。 |
备注:
- OnComplete和OnSuccess的区别:OnComplete是获取了Http请求时引发的,此时页面还没有进行更新,OnSuccess是在页面已经更新后引发的。
- 当加载数据须要花较长时候,为了避免假死状况,该当给用户一个反馈信息,如“正在加载…”字样。在 MVC 的 Unobtrusive Ajax 中经用AjaxOptions选项的 LoadingElementId 和 LoadingElementDuration 两个属性可轻松做到这一点,例如下面的设置:
1 | AjaxOptions ajaxOpts = new AjaxOptions { |
- 对于URL,如果我们设置如下:
1 | AjaxOptions ajaxOpts = new AjaxOptions { |
然后查看它生成的 form 属性:
1 | <form id="form0" action="/People/GetPeople" method="post" data-ajax-url="/People/GetPeopleData" data-ajax-="#tableBody" |
它生成了两个 Url,分别为 action 属性 和 data-ajax-url 属性的值,前者是 Ajax.BeginForm() 办法按照当前 controller 和 action 名称生成的,后者是 AjaxOptions 的 Url 属性生成的。当浏览器没有禁用 JavaScript 时,Unobtrusive Ajax JS库会获取 data-ajax-url 属性的值作为 Url 产生 ajax 恳求。当浏览器禁用了 JavaScript 时,天然 action 属性的值决定了默示提交的 Url,自然访问该页面。固然局部未能刷新,但不会让用户体验很差。
使用Html.ActionLink方法的一个栗子:
1 | @Ajax.ActionLink("点击我", "getEntry", new { id = item.Id }, new AjaxOptions |
说明:“点击我”是生产的超链接文字;“getEntry”是当前控制器的Action方法;id = item.Id是向Action方法传递的参数;HttpMethod = “Post”, 说明Ajax请求是post方式的;UpdateTargetId = “detailsID”说明了要更新的html块的Id标记元素;InsertionMode = InsertionMode.Replace说明是替换ID为detailsID的元素里边的内容。
实际应用:
使用Ajax.ActionLink请求返回值为 Json格式的Controller方法
在Index.cshtml中使用ActionLink,如下:
1 | @Ajax.ActionLink("点击我", "JsonDetails", new { id = item.Id }, |
相应的Controller:
1 | public ActionResult JsonDetails(int id = 0) |
同时需要在Index.cshtml中添加请求成功的相应js函数Show,以便更新ID属性为detailsID的DIV内容:
1 | <script type="text/javascript"> |
使用Ajax.ActionLink 请求返回值为PartialView格式的Controller方法
在Index.cshtml中
1 | @Ajax.ActionLink("AjaxPartialView", "Details", new { id = item.Id }, |
相应的Controller:
1 | public ActionResult Details(int id = 0) |
在这里我们使用Request.IsAjaxRequest()来判断是否为Ajax请求,如果是则返回PartialView,否则返回View。最后,返回的内容会直接更新到ID属性为detailsID的DIV中。
Ajax.BeginForm
这个方法用于异步提交表单,比如一个新增信息的页面Create.cshtml,下面的代码会使表单以Ajax方式提交
1 | MvcApplication5.Models.GuestbookEntry |
控制器的代码如下:
1 | [HttpPost] |
注:
貌似上面的Ajax方法很方便,但是它的工作原理可能大家不是很清楚,这里就大概说一下吧~
当调用 Ajax.BeginForm 方法后,经由选项 AjaxOptions 对象设置的属性将会被转化成 form 表单的属性,这些属性以 data-ajax 开首,如本示例生成的 form 表单:
1 | <form action="/GuestBook/Create" data-ajax="true" data-ajax-mode="replace" data-ajax-="#tableBody" id="form0" method="post"> |
当 Create.cshtml 视图加载完成并浮现 Html 页面时,jquery.unobtrusive-ajax.js 库会寻找所有 data-ajax == true的元素,然后按照其它以 data-ajax 开头的属性值,jQuery 库中的函数将知道如何去执行 Ajax 请求。
基于JQuery的Ajax
使用JQuery的Ajax请求返回值为 Json格式的Controller方法
原理就是用JQuery的Ajax方法请求Action方法,返回值设为JSON,然后对JSON数据进行处理,例如用js函数进行处理
举个栗子:
1 | <script type="text/javascript" language="javascript"> |
使用JQuery的Ajax 请求返回值为PartialView格式的Controller方法
假设有这样的一个Model:
1 | namespace MvcApplication1.Models |
通过JQuery异步加载分部视图,Home/Index.cshtml:
1 | @{ |
HomeController控制器中:
1 | using System.Collections.Generic; |
分部视图TeamY.cshtml:
1 | @model IEnumerable<MvcApplication1.Models.Team> |
3、基于JQuery的表单异步提交
举个栗子吧:
1 | <script type="text/javascript"> |
但是我觉得如果表单提交的数据少的话,可以用这种,如果多的话,就没有必要了,用MVC自带的更好
如何提高Ajax性能
1、适当使用缓存机制
2、使用CDN内容分发来访问Jquery脚本:
(1)自己公司架设CDN服务器
(2)使用第三方公司的,比如微软,谷歌等公司的CDN,但有时候不太靠谱
3、JS/CSS文件的打包合并(Bundling)及压缩(Minification)
将多个JS或CSS文件打包合并成一个文件,并在网站发布之后进行压缩,从而减少HTTP请求次数,提高网络加载速度和页面解析速度。压缩功能实现了对javascript脚本和CSS进行压缩的功能,它能够去除脚本或样式中不必要的空白和注释,同时能够优化脚本变量名的长度
例如在BundleConfig.cs里面配置捆绑js和css文件:
1 | using System.Web; |
记得在Global.asax中注册一下:
1 | BundleConfig.RegisterBundles(BundleTable.Bundles); |
页面引用时可以这样引用:
1 |
|
启用JS/CSS文件压缩合并:
- Web.config中配置
1 | <compilation debug="false" targetFramework="4.0" /> |
- 在BundleConfig.cs或Global.asax中添加以下代码即可:
1 | BundleTable.EnableOptimizations = true; |
4、最好将js脚本文件放在view页面下面一点
关于ASP.NET MVC和Ajax的故事,暂且讲到这里吧!