You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails/JQuery技术问题:如何在js.erb中传值及实现价格联动更新

问题1:在js.erb文件中实现jQuery向嵌入式Ruby传递数据

其实js.erb是服务器端渲染的JavaScript模板,它本身是先在服务器执行Ruby代码,生成可执行的JS后再发给浏览器的。所以直接让jQuery“传数据”给js.erb里的Ruby不太对——正确的逻辑是:前端用jQuery发AJAX请求把数据传给后台控制器(Ruby编写),控制器处理完后,再通过js.erb模板把处理结果(或需要的变量)注入到JS中,最终在浏览器执行。

给你举个完整的例子:

  1. 前端发起AJAX请求(携带数据)
    可以在视图里直接写这段JS,也可以放在单独的JS文件中:

    $('#send-data-btn').click(function() {
      // 准备要传给后台的数据
      const userInput = {
        product_id: 10,
        quantity: 3
      };
    
      $.ajax({
        url: '/products/update_quantity', // 对应后台的路由地址
        method: 'POST',
        data: userInput,
        dataType: 'script' // 告诉服务器我们要接收JS格式的响应
      });
    });
    
  2. 后台控制器接收并处理数据
    在对应的控制器中编写处理逻辑:

    # app/controllers/products_controller.rb
    def update_quantity
      @product = Product.find(params[:product_id])
      @new_quantity = params[:quantity].to_i
    
      # 这里可以添加数据库操作,比如更新产品库存
      # @product.update(stock: @product.stock - @new_quantity)
    end
    
  3. 用js.erb返回处理结果
    创建对应的js.erb模板,里面可以直接使用控制器的@变量,生成浏览器能执行的JS代码:

    // app/views/products/update_quantity.js.erb
    // 用j(escape_javascript的简写)转义特殊字符,避免JS语法错误
    alert("已处理产品<%= j @product.id %>,数量:<%= j @new_quantity %>");
    // 也可以直接操作DOM更新页面内容
    $('#product-stock').text("剩余库存:<%= j @product.stock %>");
    

核心要记住:js.erb是服务器先跑Ruby代码再输出JS,所以前端数据必须先通过AJAX传到后台,才能被Ruby获取到。


问题2:下拉选择框选中后更新对应ProductPrice的价格到span标签

给你两种方案,你可以根据场景选择:

方案1:前端缓存数据(无需AJAX,响应更快)

如果产品定价数据不会实时变化,直接把所有价格提前渲染到前端的JS对象中,监听下拉框变化后直接取值更新span即可:

修改你的视图代码如下:

<label>Size</label>
<select id="volumeinfo" name="volumeinfo">
  <%= options_from_collection_for_select(@product.prices, :id, :volume_info) %>
</select>
<span id="price"></span>

<script>
// 把所有ProductPrice的id和价格对应关系存成JS对象
const priceLookup = {
  <% @product.prices.each do |price_item| %>
    <%= price_item.id %>: <%= price_item.price %>,
  <% end %>
};

// 监听下拉框的change事件
$('#volumeinfo').on('change', function() {
  const selectedPriceId = $(this).val();
  // 从缓存中取出对应价格,更新到span标签(可以按需添加价格格式,比如$符号)
  $('#price').text("$" + priceLookup[selectedPriceId]);
});

// 页面加载完成时,默认显示第一个选项的价格
$(document).ready(function() {
  const defaultPriceId = $('#volumeinfo').val();
  $('#price').text("$" + priceLookup[defaultPriceId]);
});
</script>

方案2:AJAX请求后台获取实时价格

如果价格可能动态变化(比如后台会随时更新),就用AJAX每次选中后去后台获取最新价格:

  1. 视图中的JS代码

    $('#volumeinfo').on('change', function() {
      const priceId = $(this).val();
      
      $.ajax({
        url: `/product_prices/${priceId}`, // 对应后台的路由地址
        method: 'GET',
        dataType: 'json',
        success: function(response) {
          // 拿到后台返回的价格,更新span标签
          $('#price').text("$" + response.price);
        },
        error: function() {
          $('#price').text("获取价格失败");
        }
      });
    });
    
    // 页面加载完成时,默认请求一次第一个选项的价格
    $(document).ready(function() {
      const defaultPriceId = $('#volumeinfo').val();
      $.ajax({
        url: `/product_prices/${defaultPriceId}`,
        method: 'GET',
        dataType: 'json',
        success: function(response) {
          $('#price').text("$" + response.price);
        }
      });
    });
    
  2. 后台控制器与路由配置
    首先在ProductPricesController中添加show动作,返回JSON格式的价格数据:

    # app/controllers/product_prices_controller.rb
    def show
      @product_price = ProductPrice.find(params[:id])
      render json: { price: @product_price.price }
    end
    

    然后在routes.rb中添加对应的路由:

    resources :product_prices, only: [:show]
    

两种方案各有优劣:方案1无需发送请求,响应速度快;方案2能获取到最新的价格数据,适合价格频繁变动的场景。


内容的提问来源于stack exchange,提问作者David S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:36:01