Rails Vuejs Webpacker:传递实例变量数据

时间:2017-07-27 22:19:05

标签: ruby-on-rails vue.js vuejs2 instance-variables webpacker

我正在尝试学习如何使用Vuesjs构建一个带有Vuejs的应用程序,这是通过Webpacker gem生成的。

$ rails new myvueapp --webpack=vue

如何在Vue组件之间传回实例变量数据,以便将数据导入/导出数据库?

让我们举例说,我有一个带有用户名和电子邮件字段的用户模型。是否有一个简单的示例,说明如何将实例变量@user,数据从控制器传递给组件?

我相信有两种方法可以做到这一点:

(1)在控制器中,使用render :json => @user,然后使用fetch API或Axios之类的东西来检索.vue组件中的数据。

- 或 -

(2)在视图中使用类似示例<%= javascript_pack_tag 'hello_vue' %><%= content_tag ... %>的内容。

当我执行此<%= javascript_pack_tag 'hello_vue' %>示例时,我可以看到&#34; Hello Vue!&#34;来自组件中的数据&#34; message&#34;变量,但我无法找到实例变量数据的示例,例如:@user数据,传入和传出Rails。

非常感谢有关如何传递@user数据的任何示例。

谢谢。

4 个答案:

答案 0 :(得分:1)

我不是100%肯定你想要完成的任务,但我可以想到两种方法来做到这一点。

  1. 在表单上使用curl -X GET "Content-Type: application/json" -d @data.json localhost:8080/path/to.json 。无论检索或更新任何值,都可以立即在Vue实例中使用。 (例如data.json

  2. 使用数据属性。我们假设您的控制器具有v-model变量。

  3. 然后在你看来,你可以做类似的事情(这可能不是100%正确,因为它只是从内存中):

    <%= f.input :username, input_html: { 'v-model': 'username' } %>

    然后您可以使用JavaScript访问数据属性。在这些示例中,由于两者都是表单,因此最好使用@user,但您可以将数据属性用于非表单内容。例如,我经常使用AJAX请求中使用的URI的数据属性,这可能因测试站点而异,等等。

答案 1 :(得分:1)

我做了一些有效的事情,但我却不太喜欢:在window范围内创建一个方法,如:

// app/javascript/packs/some_app.js

window.someAppPack = function (var1, var2) {
  // ...
  new Vue({
    // ...
    data () {
      return {
        var1,
        var2,
      }
    }
    // ...
  })
}

在Rails模板中:

<%= javascript_pack_tag 'somePack' %>

<script>
  someAppPack(#{raw @var1.to_json}, #{raw @var2.to_json})
</script>

这对我来说似乎很脏,我想知道这样做的好处:

  • Vue应用程序应该是可响应的,因此数据 可能会在某个时间进行更新,并会调用JSON资源。这使得传递原始数据毫无意义。
  • 如果Vue仅用于使页面的某些部分具有反应性,那么当我们可以在标准Rails管道中使用“嵌入式” Vue时,为什么还要使用所有webpack内容?

答案 2 :(得分:1)

我认为我遇到了同样的问题,但是道具帮助了我。

app / views / ** / *。html.erb

<div id="app" data-initial-value="#{raw(html_escape(@var.to_json))}"></div>
<%= javascript_pack_tag 'app' %>

app / javascript / packs / app.ts

import Vue from 'vue'
import App from '../app.vue'

Vue.config.productionTip = false;

document.addEventListener('DOMContentLoaded', () => {
    const app = new Vue({
        render: h => h(App, {
            props:{
                value: JSON.parse(document.querySelector("#app").dataset.initialValue)
            }
        })
    }).$mount()
    document.body.appendChild(app.$el)
})

app / javascript / app.vue

<template>
  <div>
  {{ value.content }}
  </div>
</template>

<script lang="ts">
export default {
  name: "App",
  props: {
    value: Object
  }
};
</script>

答案 3 :(得分:1)

我找到了一种利用宝石gon的力量来完成这项工作的方法。

  1. 在控制器中
class MyController < ApplicationController
  def index
    @user = User.first
    gon.user = @user
  end
end
  1. 布局中的
# app/views/layouts/application.html.erb
<%= Gon::Base.render_data %>
  1. 在webpacker的条目文件中
// app/javascript/packs/hello_vue.js
import Vue from 'vue'
import HelloVue from '../views/HelloVue.vue'

window.addEventListener('load', () => {
  const app = new Vue({
    el: document.getElementById('div-you-want-to-mount'),
    components: { HelloVue },
    render: h => h(HelloVue, { props: gon })
  }).$mount()
})
  1. 在HelloVue.vue中
<template>
  <div id="hello">
    User: {{ user }}
  </div>
</template>

<script>
export default {
  props: ['user']
}
</script>