JavaScript 如何把 js 变量加到加到 render 的 hash 中?

zix · 2016年09月29日 · 最后由 zix 回复于 2016年09月29日 · 2568 次阅读

js 生成了一个数组,我现在想把这个数组传到 erb 中。。要怎么做呢? 我的最终目的是根据这个数组生成一个表单

aArray = [1,2,3,4]
$("#player_role").append("<%= escape_javascript( render 'games/player_role' ,:player => aArray) %>");

这样是错误的。。但是

aArray = [1,2,3,4]
$("#player_role").append("<%= escape_javascript( render 'games/player_role' ,:player => [1,2,3,4]) %>");

这样能传递过去。。说明可以传递数组。

楼主没有理解渲染的机制。erb 是服务器端渲染的模板,渲染后的 HTML 下载到浏览器,浏览器才开始渲染 HTML 跟解析 js。你这种问题是倒过来的流程了,怎么可能实现呢?或者你用 ajax 的方式,先得到一个 javascript 数组,然后通过 ajax 请求将数组作为参数提交给后端,后端按照你给的参数渲染 HTML 片段,你再用 js 将这个片段替换到你想替换的位置。

#1 楼 @martin91 没想到看似简单的问题有如此深层的含义 感觉有些复杂。。有没有什么取巧的办法?

#2 楼 @zix 没有。这个问题本身不复杂也不深奥,是你没有理清楚一个请求的生命历程而已,混淆了其中的区别而已。感觉楼主需要好好阅读一下 《一次完整的 HTTP 事务是怎样一个过程?》这样的文章。

#3 楼 @martin91 我现在的流程是这样的 在页面中输入一个数字 比如 6 然后 ajax 到后端, 后端通过一个 js 程序进行计算,生成了一个数组 我现在就是想用这个生成的数组再在前端生成一个相应的表单(方便观看),也就是卡在这一步。如果用普通的 html 表单应该是没问题的,但是我想通过 erb 格式写,不知道如何处理

#4 楼 @zix 没太明白,贴下代码吧。好多概念乱蹿,你后端不是用的 Ruby,用的 Node.js?为什么 “后端通过一个 js 程序进行计算”?

#5 楼 @martin91 先是这里 填入一个数字

<%= form_for(:player) do |f| %>
  <%= f.label :sum_player, "游戏人数"%>
  <%= f.number_field :sum_player, in: 1..12, class: 'form-control',id:"sumofplayer" %>
<% end %>
<button type="button" id="myButton"  class="btn btn-primary" >
  分配角色
</button>
<p>
<%= link_to "A post", playerrole_path, remote: true ,method: :post,class: "btn btn-primary"%>
</p>
<div id="player_role">
</div>

点击按钮后 触发

def test
    respond_to do |format|
      format.js{}
    end
end

所以有一个 test.js.coffee.erb 文件,在其中计算生成数组:根据输入的数字,随机选两个人做坏人。我想根据这个数组反过来再 append 一个表单

arr = []
gRandomArr = ( arr, num_of_badman ) ->
  arr.sort ->
    return Math.random() - 0.5
  for x in arr[0...num_of_badman]
    arr[x] = 'badman'

make_role_for_players = (content,num_of_badman) ->

  $('#player_role').html('');

  if content
    for num in [0...content]
      arr.push( num )
    gRandomArr(arr,num_of_badman)
    for x,index in arr
      $('#player_role').append('<p>' + index + (if arr[index] == 'badman' then '内奸' else '') + '</p>');
    $('#player_role').append('<button type="button" id="myButton"  class="btn btn-primary" >
      确定角色
    </button>');

make_role_for_players $('#sumofplayer').val(),2


<% updated_list = escape_javascript(render 'games/player_role',:player => [1,'bandman',3,4])%>
$("#player_role").append("<%= updated_list%>");

#5 楼 @martin91 谢谢 刚学不久

#6 楼 @zix 没看出来你这个问题跟 erb 有半毛钱关系,因为你所有逻辑都不需要经过后端处理或者渲染啊,你提交了一个表单,但是你的 ruby 代码根本不需要做任何处理,这个表单对于后端来说就是废的,最后你只是返回一个 js 文件而已,这个文件里边除了 render 'games/player_role' 之外,其他全是纯 js 代码,这个文件应该是页面渲染的时候就一起给浏览器端的,而不是单独用一个 ajax 来请求啊。 这本来是一个简单问题,所有逻辑浏览器端 js 处理就完事了,结果你非得去后端绕一圈再回来,简单问题复杂化啊。

简单重构可以是以下这样的,我假设你渲染的页面是 app/views/players.html.erb

<!-- app/views/players.html.erb -->
<%= form_for(:player) do |f| %>
  <%= f.label :sum_player, "游戏人数"%>
  <%= f.number_field :sum_player, in: 1..12, class: 'form-control',id:"sumofplayer" %>
<% end %>

<button type="button" id="myButton"  class="btn btn-primary" >分配角色</button>

<!-- 这个地方的代码可以去掉
<p>
  <%= link_to "A post", playerrole_path, remote: true ,method: :post,class: "btn btn-primary"%>
</p>
-->

<div id="role-container">
  <div id="player_role"></div>

  <!-- 这个按钮固定就好了,没必要像原来一样动态添加 -->
  <button type="button" id="myButton"  class="btn btn-primary" >确定角色</button>
</div>

<script>
  // 全局变量命名空间
  App ||= {};
  // 这里预先加载角色相关信息,以供后边脚本使用
  App.playerRoles = <%== render 'games/player_role', :player => [1,'bandman',3,4]  %>;
</script>

而跟这个页面配套的脚本应该是同时下载的,里边的内容改为:

$ ->
  $playerCountInput = $('#sumofplayer')

  if $playerCountInput.length
    badManNumber = 2
    $playerRole = $('#player_role')

    gRandomArr = ( arr, num_of_badman ) ->
      for i in [0...num_of_badman]
        # 直接用随机下标就可以了,原来的方式还得整个数组重新排序,没必要
        randomIndex = parseInt(Math.random() * arr.length)
        arr[randomIndex] = 'badman'

    make_role_for_players = (content, num_of_badman) ->
      arr = [] # arr 的初始化放在函数里就好了,没必要放外边
      $playerRole.empty();    # 用 $.fn.empty() 方法更语义化,比起 $.fn.html("") 更舒服

      if content
        for num in [0...content]
          arr.push( num )
        gRandomArr(arr, num_of_badman)
        for x,index in arr
          $playerRole.append('<p>' + index + (if arr[index] == 'badman' then '内奸' else '') + '</p>');

    $playerCountInput.on "change", (e)->
      make_role_for_players $playerCountInput.val(), badManNumber

整个过程就没有任何需要往后端发送请求的必要,以上代码仅为示例,我没法运行,你自己看看吧。还不明白的话,就只能奉劝楼主老老实实重新认真学习基础知识了。

10 楼 已删除

#9 楼 @martin91 1.随机下标有个问题会有重复情况

2.其实也开始我也是这样做的…… 但是这样我不知道如何把角色信息提交到后端,所以想用 erb 格式的 form,新手,只会用这个。。 所以正确的做法如何把这个 arr 数组提交到服务器呢

zix 关闭了讨论。 10月05日 01:13
需要 登录 后方可回复, 如果你还没有账号请 注册新账号