简体   繁体   English

从子组件调用父方法(Vue.js)

[英]Call parent methods from child components (Vue.js)

I'm doing a project and I need to call parent methods from child components.我正在做一个项目,我需要从子组件调用父方法。 How can this be accomplished in Vue.js?这如何在 Vue.js 中完成?

You should use this.$emit('myEvent') inside of your child component, when you want to trigger the method in the parent.当您想触发父组件中的方法时,您应该在子组件中使用this.$emit('myEvent')

Then find your child component in the template of the parent and add an event catcher on it like this:然后在父组件的模板中找到您的子组件,并在其上添加一个事件捕获器,如下所示:

<template>
  <your-child-component @myEvent="myMethod"/>
</template>

If you want to add parameters to your method, you can add a second parameter to your emit like this:如果你想为你的方法添加参数,你可以像这样向你的发射添加第二个参数:

this.$emit("myEvent", "My parameter")

For this to work you don't have to change anything in the event "catcher", as long as the method you call has a parameter.只要您调用的方法有参数,您就不必更改“catcher”事件中的任何内容。

道具和发射

Maybe working example will make it more clear.也许工作示例会更清楚。

https://m-vue-leaflet.netlify.app/ https://m-vue-leaflet.netlify.app/

code- https://github.com/manojkmishra/vue-leaflet-mapping代码-https://github.com/manojkmishra/vue-leaflet-mapping

So here if you see there are 3 vue files in components folder.所以在这里,如果你看到 components 文件夹中有 3 个 vue 文件。 Brew.vue is parent component to BrewList.vue child component. Brew.vue 是 BrewList.vue 子组件的父组件。

Brew.vue- Parent Component Brew.vue-父组件

父组件

BrewList.vue - Child Component BrewList.vue - 子组件

子组件

Child component BrewList.vue is using emit to send mouse-over-brew & mouse-leave-brew values to parent Brew.vue.子组件 BrewList.vue 使用 emit 将 mouse-over-brew 和 mouse-leave-brew 值发送到父 Brew.vue。 Also, in case you are interested Brew.vue parent is sending brew prop to BrewList.vue child.此外,如果您有兴趣 Brew.vue 父级将 brew prop 发送到 BrewList.vue 子级。

子级向父级发射

As per docs- https://v2.vuejs.org/v2/guide/components.html#Listening-to-Child-Components-Events根据文档- https://v2.vuejs.org/v2/guide/components.html#Listening-to-Child-Components-Events

Dec, 2021 Update: 2021 年 12 月更新:

It works with $emit .它适用于$emit The name of @ callTest in parent component must be same as the name of $emit(' callTest ') in child component.父组件中@callTest的名称必须与子组件中$emit(' callTest ') 的名称相同。

Parent Component :父组件

<template>
  <Child
    @callTest="test" // Assign 'test' method to @callTest
  />
</template>

<script>
import Child from "../components/Child.vue";
import { defineComponent } from "vue";

export default defineComponent({
  name: "Parent",

  components: {
    Child,
  },

  methods: {
    test() {
      alert("Test");
    },
  }
});
</script>

Child Component :子组件

<template>
  <button @click="$emit('callTest')">Click Me</button>
</template>

<script>
import { defineComponent } from "vue";
    
export default defineComponent({
  name: "Child",
});
</script>

Again, the name of @ callTest in parent component must be same as the name of $emit(' callTest ') in child component.同样,父组件中@callTest的名称必须与子组件中 $emit(' callTest ') 的名称相同。


If you use $emit in script section, this is needed different from template section.如果您在script部分使用$emitthis需要与template部分不同。

Child Component :子组件

<template>
  <button @click="message">Click Me</button>
</template>

<script>
import { defineComponent } from "vue";
    
export default defineComponent({
  name: "Child",
  methods: {
    message() {
      this.$emit('callTest') // 'this' is needed.
    }
  }
});
</script>

If test method has 2 parameters , you need to call test method with 2 arguments in child component like below.如果test方法有2 parameters ,则需要在子组件中调用带有2 argumentstest方法,如下所示。

Parent Component :父组件

<template>
  <Child
    @callTest="test" // Assign 'test' method to @callTest
  />
</template>

<script>
import Child from "../components/Child.vue";
import { defineComponent } from "vue";

export default defineComponent({
  name: "Parent",

  omponents: {
    Child,
  },
        
  methods: {
    test(num1, num2) { // 'test' method has 2 parameters.
      alert(num1 + num2);
    },
  }
});
</script>

Child Component :子组件

<template>       // Call 'test' method with 2 arguments.                          
  <button @click="$emit('callTest', 3, 5)">Click Me</button>
</template>

<script>
import { defineComponent } from "vue";
        
export default defineComponent({
  name: "Child",
});
</script>

Ideally, this is the right way to do so: https://v2.vuejs.org/v2/guide/components.html#Listening-to-Child-Components-Events理想情况下,这是正确的方法: https://v2.vuejs.org/v2/guide/components.html#Listening-to-Child-Components-Events

On the other hand, I believe in your scenario (which I'm trying to assume cause it's not really clear), you can use this.$parent.methodName.另一方面,我相信你的场景(我试图假设它不是很清楚),你可以使用 this.$parent.methodName。

Keep in mind that the second suggestion is less clean.请记住,第二个建议不太干净。 It should be used just in case of need.它应该仅在需要时使用。

So basically, there are 2 ways to answer your question所以基本上,有两种方法可以回答你的问题

  1. Using $emit , with syntax is @使用$emit ,语法为@

  2. Passing function as props , with syntax is : The same as your example将 function 作为道具传递,语法为与您的示例相同

If you based on Vue docs and a lot of other Vue tutorials, you will see that they encourage people to use $emit event rather than passing function as props (the way you are using).如果您基于 Vue 文档和许多其他 Vue 教程,您会看到它们鼓励人们使用$emit事件,而不是function 作为道具传递(您使用的方式)。 The docs you can read here.您可以在此处阅读的文档。

https://v2.vuejs.org/v2/guide/components-custom-events.html https://v2.vuejs.org/v2/guide/components.html#Emitting-a-Value-With-an-Event https://code.tutsplus.com/tutorials/design-patterns-for-communication-between-vuejs-component--cms-32354 vue, emitting vs passing function as props https://v2.vuejs.org/v2/guide/components-custom-events.html https://v2.vuejs.org/v2/guide/components.html#Emitting-a-Value-With-an-Event https://code.tutsplus.com/tutorials/design-patterns-for-communication-between-vuejs-component--cms-32354 vue,发射与传递 function 作为道具

The reason is Vue philosophy is passing props down, emitting events up .原因是 Vue 的理念是向下传递 props,向上发射事件 Using $emit will help to mark the function triggered as a Vue event, and therefore you can use global event listener.使用$emit将有助于将触发的 function 标记为 Vue 事件,因此您可以使用全局事件监听器。 This will also may help you to separate between data flow logic and event flow logic .这也可以帮助您区分数据流逻辑事件流逻辑

However, using function as props is not wrong, and in fact, it can be used to achieve the same result.但是,使用 function 作为 props 并没有错,实际上也可以用来达到同样的效果。 In my preference, I use the 2nd way when I write a component that has a default function, and the function is only overridden when parents pass another one.在我的偏好中,当我编写一个具有默认 function 的组件时,我使用第二种方式,并且 function 仅在父母通过另一个时被覆盖。 This will help me avoid rewriting default functions many times.这将帮助我避免多次重写默认函数。

For the rest of the other cases, I will use the 1st way $emit.对于其他情况的rest,我将使用第一种方式$emit。

I did this with props.passed the parent method through props to the child component.我用 props 做到了这一点。通过 props 将父方法传递给子组件。 and accessed from the child component.并从子组件访问。

in child component在子组件中

props: ["lesson","fetchLessons"],

and accessed props like this in child component并在子组件中访问这样的道具

this.fetchLessons();

parent component父组件

<InstructorLesson  v-for="(lesson,index) in getFechedLessons" :lesson="lesson" :fetchLessons = "fetchLessons" v-bind:key="index"/>

Parent家长

<complited v-on:passData="fromChild" />

  methods: {
      fromChild(data) {
        if (data.methodCall) return this[data.methodCall]();
      }

      aFunction() {
        alert('function: a');
      }

      bFunction() {
        alert('function: b');
      }
  }

Child孩子

<template>
   <div>
    <button @click="parentCall()">Call Parent Function
    </button>
   </div>
  </template>
  methods: {
      parentCall() {
        this.$emit("passData", {methodCall: 'aFunction' });
      }
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM