簡體   English   中英

如何在沒有erb.js的情況下響應AJAX調用/為什么使用erb.js?

[英]How to respond_to AJAX call without erb.js / why use erb.js?

最近幾天,我花了很多時間來理解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

它可行,但是對我來說,這個想法似乎有一些缺點:

  • 通過擁有額外的* .js.erb文件來膨脹我的文件結構
  • 扭曲JS與其余代碼庫的物理分離
  • 當我使用HAML時,它引入了一種新的編碼方式(ERB)

現在我有兩個問題:

  1. 每個教程(到目前為止,我都看過)似乎都在推廣這種在Rails中處理AJAX響應的解決方案:為什么? 當我檢查其他較大的Rails項目(例如Diaspora)的代碼時,我似乎沒有發現它們是這樣做的-大多數對象似乎都通過$.ajax({ ... })在純JS / jQuery中處理它$.ajax({ ... }) 那么,內部使用Rails的UJS方法的主要優點是什么?

  2. 如果出於某些原因,最好使用Rails UJS-way:如何組織代碼? *.js.erb -files創建額外的目錄嗎?

  3. 將所有這些內容傳輸到我的/app/assets/javascript目錄中的純javascript文件並在jQuery中處理AJAX請求的最佳實踐是什么? 為了通過HTML的適當部分進行響應以通過JS更新DOM,我的控制器響應將如何顯示? 換句話說:我該如何響應我可以在Plain Javascript / jQuery中處理的部分內容?

提前致謝! 和我

那么,內部使用Rails的UJS方法的主要優點是什么?

js.erb是窮人的單頁體系結構(SPA)的一種形式。

它很容易從控制器返回.js響應,從而修改當前頁面,並允許您使用rails helper進行模板制作,因此您不必使用客戶端模板制作系統(如把手)。

請注意,這並不是Rails真正的內部功能。 jQuery UJS簡單地使用了Rails可以返回資源的多種格式的事實。 您可以將其與任何可以使用javascript的MVC框架一起使用。

主要優點是它非常平易近人。 對於經典的同步應用程序來說,這足夠了,這些應用程序在這里和那里想要少量的Ajax。

它給那些認為jQuery.load和script標簽無處不在的開發人員是最好的選擇,因為切成薄片的面包剛好可以用來掛自己。

缺點

  • 違反REST的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的過程,並且需要設置諸如數據綁定之類的內容以使表單顯示錯誤。 這導致代碼重復。

這是SPA框架(例如Ember和Angular)出現的地方,它們完成了客戶端中的所有模板和渲染。

我該如何處理我可以在Plain Javascript / jQuery中處理的部分內容?

您可以創建其他格式,以供控制器響應。 例如,您可以注冊"text/html-partial" MIME類型。

或創建其他路由,甚至使用查詢參數(抖動)。

但是,由於與js.erb完全相同的原因,這並不理想-它導致API糟糕,因為您的控制器將變為進程而不是面向資源的。 您最終將創建荒謬的控制器操作,只是將html片段傳遞回客戶端。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM