使用Vue-Router时如何在组件之间传递数据

Posted

技术标签:

【中文标题】使用Vue-Router时如何在组件之间传递数据【英文标题】:How to pass data between components when using Vue-Router 【发布时间】:2020-02-12 15:30:47 【问题描述】:

使用 Vue 路由器时如何将数据从一个组件传递到另一个组件?

我正在构建一个具有不同组件的简单 CRUD 应用程序。 我的组件是:

App.vue - 我渲染路由器视图的地方 Contacts.vue - 我有联系人对象数组 ContactItem.vue - 处理联系人的显示方式(从contact.vue 获取联系人作为道具 AddContact.vue - 添加新联系人 EditContact.vue - 编辑选定的联系人

AddContact 组件上,我有一个用户填写的表单,然后单击提交按钮将表单添加到Contacts.vue 的主组件,但是当我发出一个事件并在Contacts.vue 上调用它时组件,它不起作用。我没有得到任何输出,但从 devtools 我可以看到事件是从 AddContact.vue 组件触发的。

这里是Github link

<!-- App.vue -->
<template>
  <div>
    <Navbar />
    <div class="container">
      <router-view @add-contact="addContact" />
    </div>
  </div>
</template>

<script>
import Navbar from "./components/layout/Navbar";
export default 
  components: 
    Navbar
  
;
</script>
<!-- Contacts.vue -->
<template>
  <div>
    <div v-for="(contact) in contacts" :key="contact.id">
      <ContactItem :contact="contact" />
    </div>
  </div>
</template>

<script>
import ContactItem from "./ContactItem";

export default 
  components: 
    ContactItem
  ,
  data() 
    return 
      contacts: [
        
          id: 1,
          name: "John Doe",
          email: "jdoe@gmail.com",
          phone: "55-55-55"
        ,
        
          id: 2,
          name: "Karen Smith",
          email: "karen@gmail.com",
          phone: "222-222-222"
        ,
        
          id: 3,
          name: "Henry Johnson",
          email: "henry@gmail.com",
          phone: "099-099-099"
        
      ]
    ;
  ,
  methods: 
    addContact(newContact) 
      console.log(newContact);
      this.contacts = [...this.contacts, newContacts];
    
  
;
</script> 
<!-- AddContact.vue -->
<template>
  <div>
    <div class="card mb-3">
      <div class="card-header">Add Contact</div>
      <div class="card-body">
        <form @submit.prevent="addContact">
          <TextInputGroup
            label="Name"
            name="name"
            placeholder="Enter your name..."
            v-model="name"
            for="name"
          />
          <TextInputGroup
            type="email"
            label="Email"
            name="email"
            placeholder="Enter your email..."
            v-model="email"
          />
          <TextInputGroup
            type="phone"
            label="Phone"
            name="phone"
            placeholder="Enter your phone number..."
            v-model="phone"
          />

          <input type="submit" value="Add Contact" class="btn btn-block btn-light" />
        </form>
      </div>
    </div>
  </div>
</template>

<script>
import TextInputGroup from "../layout/TextInputGroup";
export default 
  components: 
    TextInputGroup
  ,
  data() 
    return 
      name: "",
      email: "",
      phone: ""
    ;
  ,
  methods: 
    addContact() 
      const newContact = 
        name: this.name,
        email: this.email,
        phone: this.phone
      ;
      this.$emit("add-contact", newContact);
    
  
;
</script>

【问题讨论】:

能否请您出示您的Contacts.vue,至少是您拥有&lt;AddContact&gt; 组件的部分及其任何事件处理方法 @Phil 我刚刚用更多代码更新了问题 那么&lt;AddContact&gt; 在哪里?它是如何包含在您的应用中的? 是的,来自&lt;router-view&gt; 我不太同意,Vue也不同意~vuejs.org/v2/style-guide/… 【参考方案1】:

嗯,还有更多方法可以在组件之间发送数据:

您可以在 main.js 文件中创建一个新的 Vue 实例并将其命名为 eventBus

  export const eventBus = new Vue();

之后,您可以在任何需要的地方导入此总线:

  import  eventBus  from "main.js"

然后你可以通过这个全局总线发送事件:

  eventBus.$emit("add-contact", newContact);

在另一个组件中,您需要再次导入此总线并在“已创建”生命周期中监听此事件:

  created()
     eventBus.$on("add-contact", function (value)
                                   console.log(value)
                               )
   

另一种方式是将其集中存储在 vuex 状态中。使用“created”,您可以调用此数据。 Created 在你的 vue 实例创建后执行

【讨论】:

它不工作。它只显示它是从根目录触发的,但我没有看到来自AddContact 输入字段的值的任何控制台日志我更新了我的 Github 存储库以反映新的变化 好吧,我明白为什么它不起作用了,因为当您添加一些联系人时,您不会切换回您的联系人,您仍然停留在添加页面上。好吧,我在 vuex 的帮助下解决了这个问题。我会给你发一个github链接来下载它。 我们开始:github.com/ilijanovic/contact-manager-master-fixed 感谢您的帮助。我知道 Vuex 很好,也知道如何使用它。我一直在寻找一种方法来做到这一点,而不会增加 Vuex 的额外复杂性并给我的代码增加更多开销。虽然,如果我可以确认唯一可行的方法是使用 Vuex,那么我希望您更新您的答案,以便我将其作为答案。 没问题,上面的这个答案只有在您立即路由回您的联系人概览时才有效。但没关系,vuex 是这里更好的选择。完成这项工作仍然有小问题,因为我使用 nuxt.js 编码并且 vuex 略有不同

以上是关于使用Vue-Router时如何在组件之间传递数据的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用服务的情况下将子组件之间的反应式表单数据传递给父组件

将自定义数据传递给 vue-router 中的 `$router.push()`

如何使用ts将数据传递给vue3中的多深度子组件

Primeng - 对话服务将数据传递给对话组件

将 Fragment 之间的数据传递给 Activity

用户授权后如何在所有子组件之间传递状态?