本篇文章主要介绍了AJAX技术的概念,以及一些简单的实现。看到这个标题,我想你也有同样的困惑,那就是…
什么是AJAX?
(这里引用wiki上的解释)
AJAX即“Asynchronous JavaScript and XML”(异步的JavaScript与XML技术),blabla…(根本就看不懂!)
那就简单点来说吧!
当年还在我小的时候,大概03年吧,我在上初一,那个时候网吧刚在我们那个小城市萌生。传奇,大话西游等第一代网游一时风靡。我抱着试一试的心态给了网吧老板两块钱想申请个账号玩玩,然后接下来的一个小时我一直在,注,册,账,号。遥记得注册的时候,填了一堆信息,提交,页面跳转,嘣!“您填写的信息有误,请重填”。然后跳转回了注册页面,以此循环。我现在就在想,如果当时ajax能普及开来,我就可以省2块钱了。
那么ajax是什么?
首先ajax是一种技术。以往的网页交互方式,用户在点击一个按钮后,比如提交按钮,用户就要等待漫长的数据和服务器的交互,期间用户无法进行任何操作,只能点根烟。而ajax所做的,就是在向服务器发送请求的时候,我们不必等待结果,而是可以同时做其他事情,等到有了结果我们可以再来处理这个事儿。
其实ajax技术早在1998年的时候就已经由微软实现了,然而直到2005年2月,Adaptive Path公司的Jesse James Garrett发表文章“Ajax: A New Approach to Web Applications”,人们读了后觉得哎呦不错哦这个屌,这之后ajax才大规模普及开来。
ajax的出现,极大的提高了web的用户体验。时至今日,即使国内IT发展再怎么落后,所有网站的登陆注册也已经实现了ajax交互。用户点填写完信息后,页面不用刷新就可以知道信息提交成功与否,哪错改哪。
我们姑且把ajax作为一种前后端分离的解决方案吧。
AJAX的优缺点
优点:
不言而喻,使用ajax的最大优点,就是能在不更新整个页面的前提下维护数据。这使得Web应用程序可以更加快速的回应用户动作。缺点:
对应于使用ajax最主要的批评就是,它可以破坏浏览器的后退功能。在这种动态更新页面的情况下,用户有时候难以回到前一个页面状态,这是因为浏览器仅能记录下history中的静态页面。用户总是希望点击一下“后退”按钮就可以取消他们前一次的操作,但是在ajax应用程序中很显然无法这样做:一个被完整读入的页面和一个已经被动态修改过的页面还是有差别的。另外一个观点认为,使用动态页面更新使得用户很难将某个特定的“状态”保存到收藏夹或者share给其他人,不过这个问题是有解决方案的:使用“URL片断标识符”(也就是我们通常称为锚点,即URL中#后面的部分)来保持追踪,目前来讲我在github中的很多readme的链接中经常看到,并且很多浏览器允许JavaScript动态更新锚点,这就使得ajax应用程序在更新显示内容的同时可以更新锚点,这些solution同时也解决了不能使用后退按钮的问题。
RoR中AJAX的简单实现
这里通过两个简单的例子来看看ajax怎么在web应用程序中实现的吧。
1、在网页中新建用户的表单(使用ajax)
-预备知识:
使用form_for 方法协助编写表单,可指定 :remote 选项,用法如下:
<%= form_for(@post,remote: true) do |f| %>
...
<% end %>
生成的 HTML 如下:
<form accept-charset="UTF-8" action="/posts" class="new_post" data-remote="true" id="new_post" method="post">
...
</form>
注意 data-remote=”true” 属性,现在这个表单不会通过常规的提交按钮方式提交,而是通过 ajax 提交,所以呢?在需要使用ajax的表单中指定remote: true
即可。
-接下来就是如何实现 create user 了:
create动作的视图(app/views/users/create.html.erb)如下:
<b>Users</b>
<%= form_for(@user,remote: true) do |f| %>
<%= f.label :name %><br>
<%= f.text_field :name %>
<%= f.submit %>
<% end %>
表单会调用 UsersController 的 create 动作。因为表单的 remote 属性为 true,所以发往 UsersController 的是 Ajax 请求,使用 JavaScript 处理。要想处理这个请求,控制器的 create 动作应该这么写:
# app/controllers/users_controller.rb
# ......
def create
@user = User.new(params[:user])
respond_to do |format|
if @user.save
format.html { redirect_to @user,notice: 'User was successfully created.' }
format.json { render json: @user,status: :created,location: @user }
else
format.html { render action: "new" }
format.json { render json: @user.errors,status: :unprocessable_entity }
end
end
end
这样一个完整的创建用户的ajax表单提交就完成了,怎么样?So easy!你妈妈都不知道你可以如此熟练的掌握ajax。
2、在chart数据加载完全之前显示网页
这又是什么鬼?抱歉刚刚我没有阐述清楚,我的意思是:我需要一个 chart 来帮助我统计blabla的信息,并显示在网页中。在我完成这个功能的时候,我发现网页加载的太慢了!简直无法忍受!后来想想读取数据库总是需要时间的吧,那我能不能让网页先加载出来呢?让用户可以看到除此之外的有用的信息, chart 部分暂时为空也没关系,稍等两秒就可以了。——很显然这是一个典型的运用 ajax 的需求。
值得一提的是,在这里我用到了amcharts,安利一下这是一个很有用的 javascript 绘制 charts 和 maps 的工具。
不多说,在config/routes.rb
中定义这样一条路由:
...
get "/chart/get-chart" => "chart#get_chart",defaults: {format: :json}
...
在视图文件(app/views/chart.haml)中:
%h3 chart_xxx
#chart-column.chart
在 amcharts 对应的 js 文件app/assets/javascripts/chart.js
中,定义这样一个function:
$.get("/chart/get-chart",function(data) {
var chart_dataflow_column = new AmCharts.AmSerialChart();
$.extend(chart_dataflow_column,_amcharts.options.dataflow_column,{
...
customize your own charts
...
"dataProvider": data
});
chart_column.write('chart-column');
chart_column.addListener("rendered","_amcharts.methods.zoom(chart_column,data)");
_amcharts.methods.zoom(chart_column,data);
});
最后,在控制器(app/controllers/chart_controller.rb)中:
def get_chart
data = @user.get_data
render json: data.to_json
end
至于你在 user.rb 中怎么定义这个 get_data 的 action,那是你自己的事情了。