使用组件调用父方法

我有一个组件,希望添加一个 click 侦听器,该侦听器在 Vue 的父模板中运行一个方法。这可能吗?

<template>
<custom-element @click="someMethod"></custom-element>
</template>


<script>
export default {
name: 'template',
methods: {
someMethod: function() {
console.log(true);
}
}
</script>
153903 次浏览

Directly from the Vue.js documentation:

In Vue, the parent-child component relationship can be summarized as props down, events up. The parent passes data down to the child via props, and the child sends messages to the parent via events...

So you need to emit a click event from your child component when something happens, which can then be used to call a method in your parent template.

If you don't want to explicitly emit an event from the child (using this.$emit('click') from your child component), you can also try to use a native click event, @click.native="someMethod".

You can either pass the parent method down to the child component via props or you can get the child component to emit either a custom or native event.

Here's a Plunker to demonstrate both approaches.

Yes!

It's possible to call a parent method from a child and it's very easy.

Each Vue component define the property $parent. From this property you can then call any method that exist in the parent.

Here is a JSFiddle that does it : https://jsfiddle.net/50qt9ce3/1/

<script src="https://unpkg.com/vue"></script>


<template id="child-template">
<span @click="someMethod">Click me!</span>
</template>


<div id="app">
<child></child>
</div>


<script>
Vue.component('child', {
template: '#child-template',
methods: {
someMethod(){
this.$parent.someMethod();
}
}
});


var app = new Vue({
el: '#app',
methods: {
someMethod(){
alert('parent');
}
}
});
</script>

Note: While it's not recommended to do this kind of thing when you are building disconnected reusable components, sometimes we are building related non-reusable component and in this case it's very handy.

Relying on calling this.$parent hides the dependency and will break when you use component libraries which create a longer child hierarchy

The prefered methods are to either:

  1. Explicitly pass methods as properties to child components (the same as passing data props)
  2. Or declare global methods as mixins

From nils's answer on Vue.js inheritance call parent method:

  1. Passing props (parent-child)

    var SomeComponentA = Vue.extend({
    methods: {
    someFunction: function () {
    // ClassA some stuff
    }
    }
    });
    
    
    var SomeComponentB = Vue.extend({
    props: [ 'someFunctionParent' ],
    methods: {
    someFunction: function () {
    // Do your stuff
    this.someFunctionParent();
    }
    }
    });
    

    and in the template of SomeComponentA:

    <some-component-b :someFunctionParent="someFunction"></some-component-b>
    
  2. Use Mixins

    If this is common functionality that you want to use in other places, using a mixin might be more idiomatic:

    var mixin = {
    methods: {
    someFunction: function() {
    // ...
    }
    }
    };
    var SomeComponentA = Vue.extend({
    mixins: [ mixin ],
    methods: {
    }
    });
    
    
    var SomeComponentB = Vue.extend({
    methods: {
    someFunctionExtended: function () {
    // Do your stuff
    this.someFunction();
    }
    }
    });
    

Further Reading

In current vue version, this solution:
Passing props (parent-child)

var SomeComponentA = Vue.extend({
methods: {
someFunction: function () {
// ClassA some stuff
}
}
});


var SomeComponentB = Vue.extend({
props: [ 'someFunctionParent' ],
methods: {
someFunction: function () {
// Do your stuff
this.someFunctionParent();
}
}
});

The HTML part:

<some-component-b someFunctionParent="someFunction"></some-component-b>

Base on this post, should be modified in this way:

<some-component-b v-bind:someFunctionParent="someFunction"></some-component-b>

You can use $root like this with vanilla Vue, but, If you use nuxt with vue that response won't work. Why? because $root is nuxt itself. Let me show you an example:

this.$root.$children[1].myRootMethod()
  • $root: As I said before, this is nuxt.

  • $children[0]: this is nuxtloading.

  • $children[1]: this is your main component, in my case, it was a basic layout with a few global components and a global mixin.

  • $children[n]: other components on your app.

Hope it helps.

Solution for Vue 3:

Another way to provide a function to a child component is to use provide/inject. The advantage is that you can avoid passing on props through multiple components, as inject can be used at any depth of child components.

Parent component:

<script setup>


import { provide } from 'vue'


myFunction(){
console.log('message from parent');
}


provide('message', myFunction);

Some child component:

<script setup>
import { inject } from 'vue'


const msg = inject('message')


//calling the injected function
msg()


</script>


Link to the docs.