vue3组件通信

举报
林太白 发表于 2025/04/21 17:47:01 2025/04/21
【摘要】 vue3组件通信

❤vue3组件通信

props 和 emit

  • 简介
  Props是Vue3中最常见的组件间传值方式  
  在父组件中定义Props将其传递给子组件
  子组件就可以访问这些数据了

  通过 `props` 向子组件传递数据,通过 `$emit` 向父组件发送事件
  可以确保数据流动的单向性和组件之间的解耦

父子组件传值

父子组件传值:父组件向子组件传值(props),子组件向父组件传值(emit)

无setup语法糖写法(Vue版本3.3 之前)

👉 父组件
// 1、引入子组件
import JMsUploadps  from './JMsUploadps.vue';

//2、在父组件上定义同名方法接收
//同名事件
<JMsUploadps  @sendImg="sendImg($event,val)" ></JMsUploadps> 

//3、父组件接收方法的参数为子组件传递的参数
function sendImg(e,row){
   console.log(e,row);
   console.log('我是子组件传递给父组件的数据');
}
👉 子组件

1、定义
emits,emits的定义是与component、setup等这些属性是同级

emits此时是作为数组,它也可以接收一个对象
2、使用

setup(props, { emit, refs }) {
    emit('addImg', '参数');
}

有时候需使用ctx.emit,其中ctx是setup中第二个参数,也就是上下文对象

setup(props,ctx) {
  ctx.emit('addImg', '参数');
}

👉完整案例(无setup语法糖)

// 父组件ChildComponent.vue
<template>
  <ChildComponent :data="parentData" @childEvent="handleChildEvent" />
</template>
<script>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';

export default {
  components: { ChildComponent },
  setup() {
    const parentData = ref('some data');
    function handleChildEvent(message) {
      console.log('Event received from child:', message);
    }

    return {
      parentData,
      handleChildEvent
    };
  }
};
</script>

// 子组件 传统写法(Options API + setup)
<template>
  <div>
    <p>Received from parent: {{ data }}</p>
    <button @click="sendEventToParent">Send event to parent</button>
  </div>
</template>

<script>
export default {
  props: {
    data: {
      type: String,
      required: true
    }
  },
  emits: ['childEvent'],
  methods: {
    sendEventToParent() {
      this.$emit('childEvent', 'Hello from child!');
    }
  }
};
</script>

setup语法糖的使用(Vue版本3.3 以后)

👉父组件

<template>
  <commentdialog ref="mychild1" @sendSubmit="handlesendSubmit"></commentdialog>
</template>

<script setup>
import { ref } from 'vue';
import commentdialog from '@/views/admin/comment/commentdialog.vue';

// 引用子组件
const mychild1 = ref(null);

// 调用子组件方法
function openDialog(row) {
  console.log(row);
  if (mychild1.value) {
    mychild1.value.openDialog(1);
  }
}

// 处理 sendSubmit 事件
function handlesendSubmit() {
  // 处理 sendSubmit 事件
}
</script>

👉子组件

<template>
  <div>
    <!-- 子组件的内容 -->
    <p>Dialog content goes here</p>
    <button @click="openDialog(1)">Open Dialog</button>
  </div>
</template>

<script setup>
import { defineExpose } from 'vue';

// 子组件方法
function openDialog(id) {
  console.log('Dialog opened with id:', id);
  // 这里可以处理打开 dialog 的逻辑
}

// 暴露 openDialog 方法给父组件
defineExpose({
  openDialog
});
</script>

👉 完整示例

🔺父组件

//父组件
//方式二 setup方式  Vue版本3.3 之后
<template>
  <ChildComponent ref="CustomerDialogRef"   @childEvent="handleChildEvent" />
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const CustomerDialogRef = ref(null);
function handleChildEvent(message) {
    console.log('Event received from child:', message);
    CustomerDialogRef.value.handleOpen();
  }
};
</script>

🔺子组件

<template>
  <button @click="notifyParent">Notify Parent</button>
</template>
<script>
import { defineComponent, toRefs } from 'vue';
export default defineComponent({
  props: {
    data: String
  },
  setup(props, { emit }) {
    const { data } = toRefs(props);
    function notifyParent() {
      emit('childEvent', 'message from child');
    }
    return {
      data,
      notifyParent
    };
  }
});
</script>

Provide/Inject 传参

Vue3中提供了一种高级的组件间传值方式。它允许祖先组件向后代组件注入数据,而不需要显式地将数据传递给中间组件

使用 provide 和 inject

provideinject 用于在组件树中共享数据,适用于多层级的组件传递。

👉 父子组件传值

🔺父组件:

<template>
  <ChildComponent />
</template>
<script>
import { provide } from 'vue';

export default {
  setup() {
    provide('sharedData', 'some value');
  }
};
</script>

🔺子组件:

<template>
  <p>Injected Data: {{ injectedData }}</p>
</template>
<script>
import { inject } from 'vue';

export default {
  setup() {
    const injectedData = inject('sharedData');

    return {
      injectedData
    };
  }
};
</script>

ref传参(甚为喜欢)

父组件使用子组件方法

方法一定要在子组件暴露出来

//父组件发送
import jidijiangshi from "@/views/jidi/jidijiangshi.vue";
<jidijiangshi ref="mychild1" @sendSubmit="handlesendSubmit"></jidijiangshi>

const mychild1 = ref()
mychild1.value.queryfromParent();
//父组件接受
const handlesendSubmit=(row)=>{
    console.log(row,'输入到A组件');
}

子组件向父组件传值和方法

//子组件
import { ref, watch,defineEmits } from 'vue'
const emit=defineEmits(['sendSubmit'])

// 子组件
// 子组件-父元素过来
const queryfromParent = (row)=>{
    console.log('子元素2')
}
// 确认
const handelSubmit = () => {
    emit('sendSubmit','222222');
}
//不会暴露任何在 <script setup> 中声明的绑定。defineExpose可以将方法主动暴露出来
defineExpose({
    queryfromParent,
})

使用 refs 访问子组件实例

在Vue 3中,$parent 属性被移除,因为 Vue 3 引入了 Composition API,这使得组件间的通信和状态管理变得更加明确和模块化。

$parent 在 Vue 2 中用于访问父组件实例,但在 Vue 3 中推荐使用其他方法来实现组件间的通信。

在vue2之中我们使用的ref和parent废弃了,使用vue2的时候会提示我们

$parent is not defined

通过 ref 获取子组件实例并访问其方法或数据。

🔺父组件:

<template>
  <ChildComponent ref="childRef" />
  <button @click="callChildMethod">Call Child Method</button>
</template>
<script>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';

export default {
  components: { ChildComponent },
  setup() {
    const childRef = ref(null);

    function callChildMethod() {
      if (childRef.value) {
        childRef.value.childMethod();
      }
    }
    return {
      childRef,
      callChildMethod
    };
  }
};
</script>

🔺子组件

<script>
import { defineComponent } from 'vue';
export default defineComponent({
  methods: {
    childMethod() {
      console.log('Method in child called,我是子组件');
    }
  }
});
</script>

❤ 错误分析

(1)Component emitted event "addImg" but it is neither declared in the emits option nor as an "onAddImg" prop.

父组件上定义同名方法与子组件上的emit 提交方法名不一致

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。