将数据传递到vue.js中的组件


92

我正在努力了解如何在vue.js中的组件之间传递数据。我已经通读了几次文档,并查看了许多与Vue相关的问题和教程,但我仍然不明白。

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

  1. 显示一个组件中的用户列表(完成)
  2. 单击(完成)链接后,将用户数据发送到新组件-请参阅底部的更新。
  3. 编辑用户数据并将其发送回原始组件(到目前为止尚未实现)

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

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

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路由器,所以我不使用道具将数据发送到新组件。相反,我需要在v链接上设置参数,然后使用过渡钩接受它。

V链接更改请参见vue-router文档中的命名路由

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

然后在组件上,将数据添加到路由选项,请参阅过渡钩子

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,
        }
   },
})

Answers:


46

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

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


如果要在添加新组件时从html传递数据。使用道具即可完成。

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

仅当将属性名称添加prop-nameprops属性时,此属性值才对组件可用。


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

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

而您要从发送数据到<my-child-A><my-child-B><my-child-A>必须分派一个事件:

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

此事件将一直沿父链进行。从任何一个父级开始,您都有一个分支将<my-child-B>您与数据一起广播事件。因此在父项中:

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

现在,此广播将沿子链传播。无论您要抓取哪个孩子,<my-child-B>我们都会添加另一个事件:

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

传递数据的第三种方法是通过v链接中的参数。当组件链完全销毁或URI更改时,使用此方法。我可以看到您已经了解它们。


决定什么类型你想要的数据通信,并选择适当的。


1
谢谢,这真的很有帮助。我唯一仍在努力的就是命名约定。即:我有user.name,我通过v-link传递了它的名字。现在,我可以编辑name变量,并将其作为名称传递回原始组件,但是原始组件没有名为name的变量。我在这里想念什么?似乎无法通过v-link传递对象?
逆行

1
您已经在传递对象。params是一个对象。可以this.user.name在您的组件中分配名称键。如果您需要帮助,请创建一个小提琴,让我知道。检查一下:vuejs.github.io/vue-router/en/route.html
notANerdDev '16

啊,好的,我现在知道了。再次感谢。感谢您的帮助,这确实使事情变得更加清晰。
逆行

6
很棒的答案,但据我所知,由于事件已过时,它将无法在2.0中使用?
rix

2
我喜欢这个答案,但是得到了评论,并且由于我正在使用Vue 2,因此我感觉我将无法使用您建议的第二种方法。是否正确恐惧?
康拉德·维特尔斯滕

23

将数据从父组件发送到子组件的最佳方法是使用props

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

  • 在子项中声明props(数组或对象
  • 通过传递给孩子 <child :name="variableOnParent">

请参见下面的演示:

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>


一个小修正:用“ <child-comp”代替“ <child”和variableAtParent ..通过<child-comp:name =“ variableAtParent”>将其传递给子级
muenalan

它仅适用于简单属性,不会更新对象引用。例如,如果您的父属性为array,并且此数组在父对象中被替换为另一个数组,则子级将看不到它。
Stan Sokolov

@StanSokolov一点也不。我确实为数组工作,请参阅:jsfiddle.net/acdcjunior/q4mank05。如果阵列没有反应性,则可能会遇到反应性问题。尝试Vue.set在此处使用,更多内容:vuejs.org/v2/guide/reactivity.html#For-Arrays
acdcjunior

如果没有反应又有什么意义呢?可以肯定的是,它在不断被新数组替换的引用上是有反应的。Vue不会将“参考更改”传播给子代,而只会对简单元素进行值更改。因此,如果在父级中覆盖了对数组的引用,则子级仍会看到旧的引用。永远不会知道父级现在可以与其他对象一起使用。
Stan Sokolov

@StanSokolov参见以下内容:jsfiddle.net/acdcjunior/ftmrne2h在父级中替换了该数组,而子级看到了该数组/对其进行了反应(单击按钮进行测试)。还是您还有其他意思?如果是这样,如果您编辑小提琴以显示它,将很有帮助
acdcjunior

15

我认为问题出在这里:

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

当给prop加上前缀时,:就表示Vue是变量,而不是字符串。因此,您不需要{{}}周围user.name。尝试:

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

编辑 - - -

以上是正确的,但是这里更大的问题是,当您更改URL并转到新的路由时,原始组件消失了。为了让第二个组件编辑父数据,第二个组件将需要是第一个组件的子组件,或者只是同一组件的一部分。


谢谢杰夫。我尝试删除{{}},但仍然遇到相同的错误。
2015年

2

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

1)将Vue实例中的参考数据作为外部对象 (data : dataObj)

2)然后,在子组件的数据返回功能中,只需返回parentScope = dataObj并瞧瞧。现在您可以做类似的事情,{{ parentScope.prop }}并且会像魅力一样工作。

祝好运!


多数民众赞成将两个组件耦合在一起,对于树和其节点来说可能是可以的,但通常不推荐使用。我会尽量避免这种情况。
十二月

1

上面提到的响应效果很好,但是如果您想在2个同级组件之间传递数据,那么也可以使用事件总线。查看此博客,这将有助于您更好地理解。

假设有两个组件:CompA和CompB具有相同的parent和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);
    })
  }

好处:

  • 更少和干净的代码。
  • 家长不应参与将数据从一个孩子的小伙伴传给另一个孩子(随着孩子数量的增长,将变得难以维护)
  • 遵循发布订阅方法。

0

我使用访问主要属性$root

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

-2

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

index.html:

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

Ammlogin.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;
            });
    },
....

Options.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>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.