【问题标题】:Passing data to components in vue.js将数据传递给 vue.js 中的组件
【发布时间】:2016-04-04 16:49:38
【问题描述】:

我很难理解如何在 vue.js 中的组件之间传递数据。我已经多次阅读文档并查看了许多与 vue 相关的问题和教程,但我仍然没有得到它。

为了解决这个问题,我希望帮助完成一个非常简单的示例

  1. 在一个组件中显示用户列表(完成)
  2. 单击(完成)链接时将用户数据发送到新组件 - 请参阅底部的更新。
  3. 编辑用户数据并将其发送回原始组件(还没有到这一步)

这是一个小提琴,在第二步失败:https://jsfiddle.net/retrogradeMT/d1a8hps0/

我知道我需要使用 props 将数据传递给新组件,但我不确定如何在功能上做到这一点。如何将数据绑定到新组件?

HTML:

    <div id="page-content">
       <router-view></router-view>
     </div>

 <template id="userBlock" >
   <ul>
     <li v-for="user in users">{{user.name}} - <a v-link="{ path: '/new' }"> Show new component</a>
     </li>
   </ul>
 </template>

  <template id="newtemp" :name ="{{user.name}}">
    <form>
      <label>Name: </label><input v-model="name">
      <input type="submit" value="Submit">
    </form>
  </template>

主要组件的js:

Vue.component('app-page', {
  template: '#userBlock',

  data: function() {
    return{

        users: []
      }
    },

ready: function () {
    this.fetchUsers();
},

methods: {
    fetchUsers: function(){
        var users = [
          {
            id: 1,
            name: 'tom'
          },
          {
            id: 2,
            name: 'brian'
          },
          {
            id: 3,
            name: 'sam'
          },
        ];

        this.$set('users', users);
     }
    }
  })

第二个组件的JS:

Vue.component('newtemp', {
  template: '#newtemp',
  props: 'name',
  data: function() {
    return {
        name: name,
        }
   },
})

更新

好的,我已经弄清楚了第二步。这是一个显示进度的新小提琴:https://jsfiddle.net/retrogradeMT/9pffnmjp/

因为我使用的是 Vue-router,所以我不使用 props 将数据发送到新组件。相反,我需要在 v-link 上设置参数,然后使用转换挂钩来接受它。

V-link变化see named routes in vue-router docs

<a v-link="{ name: 'new', params: { name: user.name }}"> Show new component</a>

然后在组件上,将数据添加到路由选项see transition hooks

Vue.component('newtemp', {
  template: '#newtemp',
  route: {
   data: function(transition) {
        transition.next({
            // saving the id which is passed in url
            name: transition.to.params.name
        });
     }
  },
 data: function() {
    return {
        name:name,
        }
   },
})

【问题讨论】:

    标签: javascript vue.js


    【解决方案1】:

    -------------以下仅适用于 Vue 1 --------------

    可以通过多种方式传递数据。方法取决于使用类型。


    如果您想在添加新组件时从 html 传递数据。这是使用道具完成的。

    <my-component prop-name="value"></my-component>
    

    仅当您将属性名称 prop-name 添加到您的 props 属性时,此属性值才可用于您的组件。


    当由于某些动态或静态事件而将数据从一个组件传递到另一个组件时。这是通过使用事件分派器和广播器来完成的。因此,例如,如果您有这样的组件结构:

    <my-parent>
        <my-child-A></my-child-A>
        <my-child-B></my-child-B>
    </my-parent>
    

    如果您想将数据从&lt;my-child-A&gt; 发送到&lt;my-child-B&gt;,那么您将不得不在&lt;my-child-A&gt; 中调度一个事件:

    this.$dispatch('event_name', data);
    

    此事件将沿父链向上传播。无论您从哪个父母那里向&lt;my-child-B&gt; 提供分支,您都可以将事件与数据一起广播。所以在父母中:

    events:{
        'event_name' : function(data){
            this.$broadcast('event_name', data);
        },
    

    现在这个广播将沿着子链传播。在您想要获取事件的任何孩子处,在我们的例子中 &lt;my-child-B&gt; 我们将添加另一个事件:

    events: {
        'event_name' : function(data){
            // Your code. 
        },
    },
    

    第三种传递数据的方式是通过v-links中的参数。当组件链被完全破坏或 URI 发生变化时使用此方法。我可以看到你已经理解它们了。


    Decide what type of data communication you want, and choose appropriately.

    【讨论】:

    • 谢谢,这真的很有帮助。我仍在努力解决的唯一问题是命名约定。即:我有 user.name 我通过 v-link 作为名称传递。我现在可以编辑 name 变量并将其作为 name 传递回原始组件,但原始组件没有名为 name 的 var。我在这里想念什么?似乎无法通过 v-link 传递对象?
    • 您已经在传递一个对象。 params 是一个对象。名称键可以分配给组件中的this.user.name。如果您需要帮助,请创建一个小提琴,并告诉我。看看这个:vuejs.github.io/vue-router/en/route.html
    • 啊,好的,我现在知道了。再次感谢。感谢您的帮助,它确实让事情变得更加清晰。
    • 很棒的答案,但据我所知,它不适用于 2.0,因为事件已被弃用?
    • 我很喜欢这个答案,但后来到了 cmets,因为我正在使用 Vue 2,我感觉我无法使用你建议的第二种方法。这是正确的担心吗?
    【解决方案2】:

    从父组件向子组件发送数据的最佳方式是使用props

    通过props将数据从父母传递给孩子

    • 在孩子中声明props(数组或object
    • 通过&lt;child :name="variableOnParent"&gt; 将其传递给孩子

    请看下面的演示:

    Vue.component('child-comp', {
      props: ['message'], // declare the props
      template: '<p>At child-comp, using props in the template: {{ message }}</p>',
      mounted: function () {
        console.log('The props are also available in JS:', this.message);
      }
    })
    
    new Vue({
      el: '#app',
      data: {
        variableAtParent: 'DATA FROM PARENT!'
      }
    })
    <script src="https://unpkg.com/vue@2.5.13/dist/vue.min.js"></script>
    
    <div id="app">
      <p>At Parent: {{ variableAtParent }}<br>And is reactive (edit it) <input v-model="variableAtParent"></p>
      <child-comp :message="variableAtParent"></child-comp>
    </div>

    【讨论】:

    • 小修复:" 将其传递给孩子
    • 它只适用于简单的属性,对象引用不会被更新。例如,如果您的父属性是数组,并且该数组在父对象中被替换为另一个数组,则子对象将看不到它。
    • @StanSokolov 一点也不。我确实为数组工作,请参阅:jsfiddle.net/acdcjunior/q4mank05。如果您的阵列不是反应性的,您可能正面临反应性问题。尝试使用Vue.set,更多信息在这里:vuejs.org/v2/guide/reactivity.html#For-Arrays
    • 如果它不是响应式的,那有什么意义呢?当然,它对不断被新数组替换的引用是反应性的。 Vue 不会将“引用更改”传播给子级,只会对简单元素进行值更改。因此,如果对数组的引用在父项中被覆盖,子项仍将看到旧的引用。永远不会知道 parent 现在使用不同的对象。
    • @StanSokolov 参见:jsfiddle.net/acdcjunior/ftmrne2h 数组在父代中被替换,子代看到/对它做出反应(单击按钮进行测试)。还是你的意思是别的?如果是这样,如果您编辑小提琴以显示它会很有帮助
    【解决方案3】:

    我认为问题出在这里:

    <template id="newtemp" :name ="{{user.name}}">
    

    当你在 props 前面加上 : 时,你是在向 Vue 表明它是一个变量,而不是一个字符串。所以你不需要{{}} 周围的user.name。试试:

    <template id="newtemp" :name ="user.name">
    

    编辑-----

    上面说的没错,但是这里更大的问题是当你改变 URL 并去一个新的路由时,原来的组件消失了。为了让第二个组件编辑父数据,第二个组件需要是第一个组件的子组件,或者只是同一组件的一部分。

    【讨论】:

    • 谢谢杰夫。我尝试删除 {{}},但仍然遇到相同的错误。
    【解决方案4】:

    我找到了一种在 Vue 中将父数据传递给组件范围的方法,我认为这有点像 hack,但也许这会对你有所帮助。

    1) 将Vue Instance中的数据作为外部对象引用(data : dataObj)

    2) 然后在子组件的数据返回函数中只返回parentScope = dataObj,瞧。现在你不能做像{{ parentScope.prop }} 这样的事情,而且会像魅力一样工作。

    祝你好运!

    【讨论】:

    • 这将两个组件耦合在一起,这对于树及其节点来说是可以的,但通常不受欢迎。我会尽量避免这种情况。
    【解决方案5】:

    上述响应效果很好,但是如果您想在 2 个兄弟组件之间传递数据,那么也可以使用事件总线。 看看这个博客,它会帮助你更好地理解。

    假设 2 个组件:CompA 和 CompB 具有相同的父级和 main.js,用于设置主 vue 应用程序。要在不涉及父组件的情况下将数据从 CompA 传递到 CompB,您可以执行以下操作。

    在 main.js 文件中,声明一个单独的全局 Vue 实例,即事件总线。

    export const bus = new Vue();
    

    在生成事件的 CompA 中:您必须将事件发送到总线。

    methods: {
          somethingHappened (){
              bus.$emit('changedSomething', 'new data');
          }
      }
    

    现在的任务是监听发出的事件,所以,在 CompB 中,你可以像这样监听。

    created (){
        bus.$on('changedSomething', (newData) => {
          console.log(newData);
        })
      }
    

    优点:

    • 精简代码。
    • 父母不应参与将数据从 1 个子组件传递到另一个子组件(随着子组件数量的增加,将变得难以维护)
    • 遵循发布-订阅方法。

    【讨论】:

      【解决方案6】:

      我使用$root 访问主要属性。

      Vue.component("example", { 
          template: `<div>$root.message</div>`
      });
      ...
      <example></example>
      

      【讨论】:

        【解决方案7】:

        一个全局的JS变量(对象)可以用来在组件之间传递数据。示例:将数据从 Amlogin.vue 传递到 Options.vue。在 Ammlogin.vue 中,rspData 被设置为来自服务器的响应。在 Options.vue 中,来自服务器的响应通过 rspData 提供。

        index.html:

        <script>
            var rspData; // global - transfer data between components
        </script>
        

        Amlogin.vue:

        ....    
        export default {
        data: function() {return vueData}, 
        methods: {
            login: function(event){
                event.preventDefault(); // otherwise the page is submitted...
                vueData.errortxt = "";
                axios.post('http://vueamm...../actions.php', { action: this.$data.action, user: this.$data.user, password: this.$data.password})
                    .then(function (response) {
                        vueData.user = '';
                        vueData.password = '';
                        // activate v-link via JS click...
                        // JSON.parse is not needed because it is already an object
                        if (response.data.result === "ok") {
                            rspData = response.data; // set global rspData
                            document.getElementById("loginid").click();
                        } else {
                            vueData.errortxt = "Felaktig avändare eller lösenord!"
                        }
                    })
                    .catch(function (error) {
                        // Wu oh! Something went wrong
                        vueData.errortxt = error.message;
                    });
            },
        ....
        

        选项.vue:

        <template>
        <main-layout>
          <p>Alternativ</p>
          <p>Resultat: {{rspData.result}}</p>
          <p>Meddelande: {{rspData.data}}</p>
          <v-link href='/'>Logga ut</v-link>
        </main-layout>
        </template>
        <script>
         import MainLayout from '../layouts/Main.vue'
         import VLink from '../components/VLink.vue'
         var optData = { rspData: rspData}; // rspData is global
         export default {
           data: function() {return optData},
           components: {
             MainLayout,
             VLink
           }
         }
        </script>
        

        【讨论】:

          猜你喜欢
          • 2023-03-04
          • 2020-06-21
          • 2018-04-17
          • 1970-01-01
          • 2017-05-25
          • 2018-04-30
          • 2017-09-04
          • 2018-07-19
          • 2017-04-14
          相关资源
          最近更新 更多