过去几天我花了很多时间来了解AJAX的不同方面。在阅读了一些介绍后,我设法了解了rails内置的UJS功能。我写的一个小玩具应用程序的例子,我想介绍一些AJAX功能...
控制器操作如下所示
class ExpenseListsController < ApplicationController
before_action :require_authentication
...
def create
@expense_list = ExpenseList.new(expense_list_params)
if @expense_list.save
respond_to do |format|
format.html do
flash[:success] = 'Created!'
render :show
end
format.js
end
else
respond_to do |format|
format.html do
@errors = @expense_list.errors
flash[:danger] = 'Something went wrong!'
render :new
end
format.js
end
end
end
...
end
在我看来,我通过remote: true
选项
相应的create.js.erb
看起来像这样
var form_field = $('.expense_lists_form');
var expenseLists = $('#expense-lists');
expenseLists.append("<%= j render @expense_list %>");
form_field.slideUp(200);
@expense_list
的模板如下所示
.col-xs-12.col-lg-3.col-md-4{id: "expense_list_#{expense_list.id}"}
.panel.panel-default
.panel-heading
= link_to expense_list.name, expense_list_path(expense_list)
.panel-body
.links
= link_to 'Modify list', edit_expense_list_path(expense_list), remote: true
= link_to 'Delete list', expense_list_path(expense_list), method: 'delete', remote: true
.description
%p
- if expense_list.description.present?
= expense_list.description
- else
%i
No description supplied, add one
=link_to 'here', edit_expense_list_path(expense_list)
.email-notification.text-muted
(Email notifications enabled)
.panel-footer
= "Expenses in #{current_month_name}:"
%b
= "#{expense_list.sum_of_exp_in_month(current_month, current_year)}€"
= "(#{expense_list.euros_left_in_month(current_month, current_year)}€ left)" if expense_list.budget_in_euro
这对我有用,但这个想法似乎有一些缺点:
现在我有两个问题:
每个教程(我到目前为止看到过)似乎都在推动这种在Rails中处理AJAX响应的解决方案:为什么?当我检查其他更大的rails项目(例如Diaspora)的代码时,我似乎没有发现它们这样做 - 大多数它们似乎通过$.ajax({ ... })
在普通的JS / jQuery中处理它。那么rails-internal UJS方法的主要优点是什么?
如果出于某种原因,首选UJS-way导轨:您如何组织代码?为*.js.erb
- 文件创建额外的目录?
将所有这些内容转移到位于我的/app/assets/javascript
目录中的普通javascript文件并在jQuery中处理AJAX请求会有什么好处?我的控制器响应如何才能响应HTML的适当部分来通过JS更新DOM?换句话说:我怎样才能回答我在Plain Javascript / jQuery中可以处理的部分内容?
提前致谢! 岸堤
答案 0 :(得分:1)
js.erb
是一种穷人单页架构(SPA)的形式。
它使得从控制器返回.js
响应变得非常容易,这些响应修改当前页面并允许您使用rails帮助程序进行模板化,这样您就不必使用客户端模板系统,例如车把。
请注意,这不是rails内部的内容。 jQuery UJS简单使用rails可以返回多种格式的资源这一事实。你可以将它用于任何可以提供javascript的MVC框架。
主要优点是非常平易近人。 它足以满足经典同步应用程序的需求,这些应用程序在这里和那里都需要少量的ajax。
它让那些认为jQuery.load
和脚本标签无处不在的开发人员是最好的事情,因为切片面包只需要足够的绳索就可以自行悬挂。
js.erb
视图通常用作操作当前页面的过程。js.erb
视图中的javascript在按请求提供服务时不会被资产管道缩小。在jquery-ujs
进入场景之前很久,我们已经发现执行ajax请求的最佳方法是JSON。
因此,如果您想以异步方式发送表单,则可以执行以下操作:
$(document).on('submit', '.ajax-form', function(e){
e.preventDefault();
var $form = $(this);
var promise = $.ajax($form.attr('action'), {
accepts: { json: 'application/json' },
data: $form.serialize(),
context: $form,
method: $form.attr('method')
});
promise.done(function(response){
// handle the response
});
});
这样,javascript逻辑可以连接成一个文件,并在javascript测试工具中单独测试。
您的后端服务器只响应简单数据,并不关心客户端使用它做什么。
但是,这确实需要您在客户端设置某种模板来处理将JSON转换为HTML,并且您需要设置数据绑定之类的东西以使您的表单显示错误。这会导致代码重复。
这就是像Ember和Angular这样的SPA框架进入图片的过程,它可以在客户端进行所有模板化和渲染。
您可以创建添加控制器响应的其他格式。例如,您可以注册"text/html-partial"
mime类型。
或创建其他路线甚至使用查询参数(颤抖)。
然而,由于与js.erb
完全相同的原因,这不太理想 - 它导致了一个糟糕的API,因为您的控制器将变为进程而不是面向资源。您最终会创建荒谬的控制器操作,只是为了将html片段传递回客户端。