Rails 如何优雅地把 Hash 参数传递给 JavaScript

caiqinghua · 2015年06月15日 · 最后由 sharpx 回复于 2016年08月08日 · 3794 次阅读

方法一、 https://ruby-china.org/topics/9844

<input type="hidden" id="order_app_id" value="<%= @order_params[‘appId’] %>"/>
<input type="hidden" id="order_time_stamp" value="<%= @order_params[‘timeStamp’] %>"/>

方法二、

<%= javascript_tag do %>
  var orderParams = {
    appId:     "<%= @order_params[:appId] %>",
    timeStamp: "<%= @order_params[:timeStamp] %>",
    nonceStr:  "<%= @order_params[:nonceStr] %>",
    package:   "<%= @order_params[:package] %>",
    signType:  "<%= @order_params[:signType] %>"
    paySign:   "<%= @order_params[:paySign] %>"
  };
<% end %>

方法三、ajax

def wechat_pay_js_params
    @params = {
        appid: 'wx7d32820a35d2458c',
        prepay_id: 'wx201506150843452f821f7b070705485969'
      }
    _prepay_id = @params[:prepay_id]
    @params = {
        appId: 'WxPay.appid',
        timeStamp: Time.now.to_i.to_s,
        nonceStr: SecureRandom.uuid.tr('-', ''),
        package: "prepay_id=#{_prepay_id}",
        signType: "MD5"
      }
    render json: @params
  end
$.ajax({
                url: '/users/wechat_pay_js_params',
                dataType: 'JSON',
                type: 'GET',
                success: function(response){
                    alert(response.appId);
                    if(response && response.appId){

                        WeixinJSBridge.invoke('getBrandWCPayRequest', response, function(res){
                            if(res.err_msg == "get_brand_wcpay_request:ok" ) {
                                window.location.href = '/orders/'+ response.orderNumber;
                            }
                            //使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
                            //因此微信团队建议,当收到ok返回时,向商户后台询问是否收到交易成功的通知,若收到通知,前端展示交易成功的界面;若此时未收到通知,商户后台主动调用查询订单$
                        });
                    }
                },
                error: function(err){
                    alert('ajax: error')
                    alert(err);
                    console.log(err);
                }
            });

别忘记设置路由

Rails.application.routes.draw do
  get '/users/wechat_pay_js_params', :to => "users#wechat_pay_js_params"
  resources :users

方法四、

WeixinJSBridge.invoke(
          'getBrandWCPayRequest',
          <%= raw @params %>,
          function (res) {
            if (res.err_msg == "get_brand_wcpay_request:ok") {
              window.location.href = '<%= wxpay_callback_order_path(@order) %>';
            } else if (res.err_msg == "get_brand_wcpay_request:cancel") {
              window.location.href = '<%= order_path(@order) %>';
            } else if (res.err_msg == "get_brand_wcpay_request:fail") {
              alert('系统错误');
            } else {
              alert('未知错误');
            }
          }
  );

你觉得哪种最优雅? 还有其他方法吗?

偏好:render json: obj 不过多个请求。

gon 是个好办法,不过感觉没必要,erb 直接 render 就行了,缺点就是代码高亮有可能会乱(RubyMine 不会)

J's 内嵌 Erb 飘过,觉得此种方法无比丑陋,但好使。

简单的 erb, 复杂的 gon

erb 里写 js 太恶心了。。。

可以放入变量然后赋值给 data,通过 data 再取出来怎么样~

#7 楼 @freelove 没理解,for example 吧

模版中存值

link_to '首页', root_path, id: 'your_id', data: {params: @order_params}

javascript 中取值

var orderParams = $('#your_id').data('params');

优点:

  1. rails 中的 data 会自动序列化对象,jquery 中的 data 会自动解析。
  2. js 代码可以随意移动,也不需要使用模版渲染,有利于分离 html 和 js。

缺点:

  1. 会有额外的对象序列化和解析。
  2. 如果对象比较大,生成的 html 中 data-params 属性的值会很大,chrome 开发工具查看 html 的时候,速度会慢一些。

#10 楼 @besfan 这方法不错,赞一个。自动系列化好像没啥用。我还是偏向于 <%= raw @params %>和 ajax 获取

#3 楼 @jasl 嗯新版的 rails to_json 已经安全了

直接 to_json 不就可以了

#{wechat_js_params(@prepay_result).to_json}
需要 登录 后方可回复, 如果你还没有账号请 注册新账号