VUE中子组件调用父组件的方法,父组件调用子组件的方法,父子组件互相传值和方法调用

文章详细介绍了在Vue.js中如何实现父子组件之间的通信,包括使用`this.$emit`触发事件、直接通过`this.$parent`调用父组件方法、将父组件方法作为props传递给子组件,以及父组件如何通过`ref`调用子组件的方法并获取其属性值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

场景:自定义一个通用组件,需要调用父组件的方法进行计算

一、使用this.$emit()向父组件触发一个事件,父组件监听这个事件即可。

父组件:

<template>
  <div>
    <child @method="method"></child>
  </div>
</template>
<script>
  import child from './components/childCompoent'
  export default {
    components: {
      child
    },
    methods: {
      method(data) {
        console.log(data+'调用父组件方法');
      }
    }
  };
</script>

子组件:

<template>
  <div>
    <button @click="method()">点击调用父组件方法</button>
  </div>
</template>
<script>
  export default {
    methods: {
      method() {
        this.$emit('method','子组件');
        //this.$emit('method');没有参数的话,直接调用即可
      }
    }
  };
</script>

二、直接在子组件中通过“this.$parent.event”来调用父组件的方法。

父组件:

<template>
  <div>
    <child></child>
  </div>
</template>
<script>
  import child from './components/childCompoent';
  export default {
    components: {
      child
    },
    methods: {
      method() {
        console.log('父组件方法');
      }
    }
  };
</script>

子组件:

<template>
  <div>
    <button @click="childMethod()">点击按钮</button>
  </div>
</template>
<script>
  export default {
    methods: {
      childMethod() {
        this.$parent.method();
      }
    }
  };
</script>

三、父组件把方法传入子组件中,在子组件里直接调用。

父组件:

<template>
  <div>
    <child :method="method"></child>
  </div>
</template>
<script>
  import child from './components/childCompoent';
  export default {
    components: {
      child
    },
    methods: {
      method() {
        console.log('父组件方法');
      }
    }
  };
</script>

子组件:

<template>
  <div>
    <button @click="childMethod()">点击按钮</button>
  </div>
</template>
<script>
  export default {
    props: {
      method: {
        type: Function,
        default: null
      }
    },
    methods: {
      childMethod() {
          this.method();
        }
      }
    }
  };
</script>
场景:父组件调用子组件的方法,父组件取值子组件的属性参数

父组件(包含的子组件引用标签中加上ref属性),这时给子组件标签使用ref,引用指向的就是子组件的实例

父组件:

<template>
  <div id="app">
    <test ref="test"/>
    <button @click="gettest">获取test组件中的值</button>
  </div>
</template>
 
<script>
import test from "./components/test.vue";
 
export default {
  components: {
    test
  },
  data() {
    return {}
  },
  methods: {
    gettest() {
      console.log(this.$refs.test.message)
    }
  }
};
</script>

子组件:

<template>
  <div>
      {{ message }}
  </div>
</template>
 
<script>
export default {
  data() {
    return {
      message: "hello world"
    }
  }
}
</script>
<think>嗯,我现在需要在Vue3中实现子组件调用父组件方法。这个问题我之前在Vue2里做过,但是Vue3的CompositionAPI可能有些不同。让我先回忆一下Vue2的做法,通常是使用$emit来触发父组件的事件,或者父组件通过props方法子组件。但Vue3可能会有其他方式,比如使用setup函数context参数。首先,子组件调用父组件方法,常见的方法有两种:一种是父组件通过props递函数给子组件子组件调用该函数;另一种是子组件触发一个事件,父组件监听这个事件并执行方法。这两种方式在Vue3中应该仍然适用,但可能写法上有所不同,尤其是在使用CompositionAPI的时候。比如,使用props的方式,父组件将一个方法作为prop递给子组件子组件在setup中接收这个prop,然后在需要的时候调用它。不过需要注意,props应该是响应式的,所以递的函数可能需要用ref或者reactive包裹吗?或者直接递函数引用即可?另一种方式是使用emit,子组件通过emit触发一个事件,父组件在模板中监听这个事件,并绑定对应的处理函数。这时候在子组件的setup中,需要通过context.emit来触发事件。例如,在子组件调用emit('some-event'),父组件那边用@some-event="handleEvent"来响应。另外,可能还有其他方法,比如使用provide/inject,父组件提供一个方法子组件注入并使用。不过这种方法可能更适合跨层级组件,而直接的父子关系可能用props或emit更合适。现在需要具体实现的话,先考虑emit的方式。在子组件中,setup函数的第二个参数是context,其中包含emit方法。所以在子组件里,可以调用context.emit('event-name'),然后父组件监听这个事件。或者,如果父组件方法作为prop,子组件直接调用该prop函数。例如,父组件递一个名为onClick的prop,子组件在按钮点击时调用props.onClick()。那在Vue3的Composition API中,子组件的setup函数接收propscontext。比如:子组件: ```javascriptsetup(props, {emit }){const handleClick =() =>{emit('custom-event','data');};return {handleClick}; }``` 父组件模板中: ```vue<ChildComponent @custom-event="handleCustomEvent"/> ```父组件方法handleCustomEvent会被调用。 或者,父组件通过props递函数:父组件:```vue<ChildComponent:onAction="handleAction"/> ```子组件在props中声明onAction,然后在需要的时候调用props.onAction()。 这两种方法哪个更合适呢?一般来说,推荐使用emit的方式,因为这是Vue的推荐模式,通过事件进行通信,保持数据流的清晰。而props递函数可能适用于更简单的场景,或者当需要更直接的回调时。 另外,在Vue3中,可以使用v-model的自定义事件或者.sync修饰符吗?不过这可能更多用于双向绑定,而不是直接调用方法。还有一种情况,如果父组件方法需要暴露给子组件通过模板ref访问,那么父组件可能需要使用defineExpose来暴露方法,但这种情况可能较少见,通常还是通过事件或props。所以,总结一下,主要的两种方法是通过emit事件,或者递props函数。现在需要给出具体的代码示例。比如,使用emit的例子: 子组件ChildComponent.vue的代码: ```vue<script setup> constemit =defineEmits(['callParentMethod']);const triggerParentMethod =() =>{emit('callParentMethod','参数数据');};</script><template><button@click="triggerParentMethod">调用父组件方法</button></template>```父组件中使用:```vue<template><ChildComponent@call-parent-method="handleCall"/></template><scriptsetup>importChildComponentfrom'./ChildComponent.vue';consthandleCall=(data)=>{console.log('父组件方法调用,收到数据:',data);};</script>```另一种方式,通过props递函数:父组件递函数:```vue<template><ChildComponent :onAction="handleAction" /></template> <scriptsetup>import ChildComponent from'./ChildComponent.vue';const handleAction =(data) =>{console.log('父组件方法调用,数据:',data);}; </script>``` 子组件ChildComponent.vue:```vue<scriptsetup>const props= defineProps({onAction:Function}); consttrigger =() =>{props.onAction('参数');}; </script><template><button@click="trigger">触发</button> </template>``` 这两种方法都是可行的,但通常推荐使用emit的方式,因为这样更符合Vue的事件驱动模式,尤其是在需要递数据时,事件的方式更清晰。而props递函数可能在需要更紧密耦合的情况下使用,比如当父组件的函数需要直接作为子组件的一个回调时。 另外,在Vue3的<script setup>语法中,defineEmitsdefineProps都是编译器宏,不需要显式导入。所以在子组件中使用defineEmits来定义事件,然后在需要的时候触发emit。需要注意的是,事件名在模板中使用kebab-case,例如callParentMethod在模板中应该写成@call-parent-method,而emit的时候使用原驼峰命名或者用字符串形式。不过Vue会自动转换,所以emit('callParentMethod')模板中的@call-parent-method是匹配的。 所以,正确的示例应该是父组件监听@call-parent-method,而子组件emit('callParentMethod'),或者emit的时候使用kebab-case,但根据Vue的约定,建议在emit时使用原事件名,而模板中使用kebab-case。总结,子组件调用父组件方法可以通过两种方式实现:emit事件或递函数prop。具体代码如上所示。</think>在Vue3中,子组件调用父组件方法主要有两种方式:通过自定义事件通过props递函数。以下是具体实现方案: ### 方案1:使用自定义事件(推荐) ```vue <!-- 父组件 ParentComponent.vue --> <template> <child-component @call-parent="handleParentMethod"/> </template> <script setup> import ChildComponent from './ChildComponent.vue' const handleParentMethod = (data) => { console.log('父组件收到数据:', data) // 执行父组件逻辑 } </script> <!-- 子组件 ChildComponent.vue --> <template> <button @click="triggerEvent">触发父组件方法</button> </template> <script setup> const emit = defineEmits(['call-parent']) const triggerEvent = () => { emit('call-parent', { message: '来自子组件的数据' }) } </script> ``` ### 方案2:通过props递函数 ```vue <!-- 父组件 ParentComponent.vue --> <template> <child-component :parent-fn="handleParentMethod"/> </template> <script setup> import ChildComponent from './ChildComponent.vue' const handleParentMethod = (data) => { console.log('父组件收到数据:', data) // 执行父组件逻辑 } </script> <!-- 子组件 ChildComponent.vue --> <template> <button @click="props.parentFn({ message: '子组件数据' })">调用父函数</button> </template> <script setup> const props = defineProps({ parentFn: { type: Function, required: true } }) </script> ``` **解释说明:** 1. **自定义事件方式**(方案1): - 使用`defineEmits`定义可触发的事件列表 - 通过`emit()`函数触发事件并递参数 - 父组件使用`v-on`(简写`@`)监听子组件事件 2. **props递函数方式**(方案2): - 父组件通过prop递函数引用给子组件 - 子组件通过`defineProps`接收函数类型的prop - 直接调用接收到的函数并递参数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

庞胖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值