从子组件调用父函数会在 Vue.js 中引发错误

Posted

技术标签:

【中文标题】从子组件调用父函数会在 Vue.js 中引发错误【英文标题】:Calling a parent function from a child component raises an error in Vue.js 【发布时间】:2021-02-19 11:21:30 【问题描述】:

我的父组件中有一个导航抽屉子组件。

MainComponent.vue

<template>
<v-app>
<div>
    <NavigationComponent></NavigationComponent>
</div>
</v-app>
</template>

现在,在子组件(导航抽屉)中,我尝试通过以下方式从 MainComponent 调用一个函数:

this.$parent._appendUser(arr);

我有一个类似的父子组件,它在父子之间调用一个函数,但我不知道为什么这个给我一个错误提示:

TypeError: this.$parent._appendUser 不是函数

父组件 - MainComponent.vue

<template>
<v-app>
<div class="container" style="padding: 0 !important">
<div class="row">
</div>
<AddInstrumentDrawer :add_instrument_drawer_watcher="add_instrument_drawer_watcher"></AddInstrumentDrawer>
</div>
</v-app>
</template>

<script>
import AddInstrumentDrawer from './shared/AddInstrumentDrawer.vue'

export default 
    name: 'user-profile',
    components:  AddInstrumentDrawer ,
    data: () => (
        profile_image_drawer_watcher: 1,
        add_instrument_drawer_watcher: 1,
    ),
    methods: 
        appendinstrument(arr) 
            alert(arr);
            /*for (let i = 0; i < arr.length; i++) 
                this.profile_data.instruments.push(arr[i]);
             */
        ,
    

</script>

子组件

<template>
<v-app>
<div>
<v-navigation-drawer v-model="add_drawer" fixed temporary right 
        disable-resize-watcher disable-route-watcher
        style="z-index: 101 !important">
    <div class="drawer-footer">
        <div class="drawer-footer-content-2">
            <button type="button" class="btn mx-1" @click="test()">Save changes</button>
        </div>
    </div>
</v-navigation-drawer>
</div>
</v-app>
</template>

<script>
    
export default 
    name: 'add-instrument-drawer',
    components:   ,
    props: ['add_instrument_drawer_watcher'],
    data: () => (
        add_drawer: false,
    ),
    watch: 
        add_instrument_drawer_watcher: function(n, o) 
            this.add_drawer = !this.add_drawer;
        ,
    ,
    methods: 
        test() 
            this.$parent.appendinstrument('test');
        ,
    ,

</script>

【问题讨论】:

请分享子组件的代码和父方法 @BoussadjraBrahim 我编辑并提供了代码。我希望它有用 【参考方案1】:

您不应该使用 this.$parent.someMethod() 调用父方法,但您必须 emit 将自定义事件从子组件发送到以父方法作为处理程序的父组件:

   <AddInstrumentDrawer 
     @append-instrument="appendinstrument"

     :add_instrument_drawer_watcher="add_instrument_drawer_watcher"></AddInstrumentDrawer>

在子组件中:

    methods: 
        test() 
            this.$emit('append-instrument','test');
        ,
    ,

【讨论】:

谢谢伙计。我一直在使用this.$parent.function(),但这是第一次不起作用。你能解释一下为什么吗? 您应该尊重组件之间的流程,父组件将道具传递给子组件,并且子组件会发出事件以更新父属性,请检查此vuejs.org/v2/guide/…【参考方案2】:

从子组件调用父方法是一种不好的做法。组件不应该知道父实现。我建议您在导航抽屉中发出一个事件并在主组件中处理该事件

//Navigation.vue

$emit('append-user', arr)

//Main.vue
<Navigation @append-user="appendUser" />

这样您就可以将导航组件放置在任何组件中。

关于 $parent 的另一件事是它不引用包含目标的组件,而是引用组件树中放置组件的直接组件(考虑 DOM 遍历)

//Main.vue
<ComA>
   <ComB />
</ComA>

ComB 内部 $parent 将引用 ComA 而不是主要组件

【讨论】:

以上是关于从子组件调用父函数会在 Vue.js 中引发错误的主要内容,如果未能解决你的问题,请参考以下文章

无法在 Vue.JS 上捕获自定义事件

从子组件调用父函数的父级

从子组件调用父函数

如何在不调用事件的情况下将数据从子级发送到父级(vue 2)

如何将父组件函数传递给子组件,然后从子 AngularJS 内部调用它

从子组件mounted()函数(Vue.js 2)列表中只收到一个发射[重复]