Vue3组件间常用通信方式

Vue3中组件间通信主要通过props/$emit、$refs、provide/inject、v-model以及Vuex实现。props用于父向子传值,$emit配合子组件方法触发父组件更新。$refs允许直接访问子组件属性和方法。provide/inject能实现祖先到子孙的跨级通信。v-model提供了双向数据绑定的便捷方式。Vuex作为状态管理库,集中管理应用的状态。

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

在Vue 3中,组件间通信的方式与Vue 2大致相同,主要包括以下几种方式:

目录

一、props / $emit

二、$refs

三、provide / inject

四、v-model

五、Vuex


一、props / $emit

使用props和$emit是Vue 3中最基本的组件间通信方式。一个组件可以通过props向它的子组件传递数据,子组件则可以通过$emit触发一个事件,并将数据传递给父组件。 

父组件:

<template>
  <child :message="msg" @update="handleUpdate"></child>
</template>

<script>
import Child from './Child.vue';

export default {
  components: {
    Child,
  },
  data() {
    return {
      msg: 'Hello, child!',
    };
  },
  methods: {
    handleUpdate(data) {
      this.msg = data;
    },
  },
};
</script>

 子组件:

<template>
  <div>
    <p>{{ message }}</p>
    <button @click="handleClick">Update Message</button>
  </div>
</template>

<script>
export default {
  props: {
    message: String,
  },
  methods: {
    handleClick() {
      this.$emit('update', 'New message from child');
    },
  },
};
</script>

二、$refs

使用$refs可以在父组件中访问子组件的属性和方法。

父组件:

<template>
  <div>
    <child ref="child"></child>
    <button @click="handleClick">Call Child Method</button>
  </div>
</template>

<script>
import Child from './Child.vue';

export default {
  components: {
    Child,
  },
  methods: {
    handleClick() {
      this.$refs.child.sayHello();
    },
  },
};
</script>

 子组件:

<template>
  <div>
    <p>Hello, I am a child component</p>
  </div>
</template>

<script>
export default {
  methods: {
    sayHello() {
      console.log('Hello from child component!');
    },
  },
};
</script>

三、provide / inject

使用provide和inject可以在祖先组件中向子孙组件传递数据,而不需要显式地通过props和$emit传递。

祖先组件:

<template>
  <div>
    <child></child>
  </div>
</template>

<script>
import Child from './Child.vue';

export default {
  components: {
    Child,
  },
  provide() {
    return {
      message: 'Hello from ancestor component!',
    };
  },
};
</script>

子孙组件:

<template>
  <div>
    <grandchild></grandchild>
  </div>
</template>

<script>
import Grandchild from './Grandchild.vue';

export default {
  components: {
    Grandchild,
  },
};
</script>

孙子组件:

<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  inject: ['message'],
};
</script>

四、v-model

v-model相当于自定义事件的语法糖,雨溪可能觉得你使用自定义事件的方式进行组件间的通信,怕你写的代码太多了有点受累,于是就推出了v-model双向数据绑定的方式进行组件间的通信。其中v-model包括两种写法。

第一种:v-model:自定义事件名 ==>$emit('update:自定义事件名',值)

第二种:v-model=                     ==>$emit('update:model-value',值)    使用默认的事件名model-value

第一种方式代码示例:

<body>
    <!-- 在子组件中使用点击按钮改变父组件中的值 -->
    <div id="app">
      num:{{num}}
      <!-- v-model后面有属性名(随便定义)  则update后面也要加这个属性名 实现双向数据绑定 -->
      <ds v-model:x="num"></ds>
    </div>
  </body>
  <script>
    let app = Vue.createApp({
      data() {
        return {
          num: 1,
        };
      },
    });
    // 定义组件
    app.component("ds", {
      props: [],
      data() {
        return {
          a: 1,
        };
      },
      template: `
        <button @click="add">a:{{a}}</button>
      `,
      methods: {
        add() {
          this.a++;
          this.$emit("update:x", this.a);
        },
      },
    });
    app.mount("#app");
  </script>

第二种方式代码示例: 

<body>
    <!-- 在子组件中使用点击按钮改变父组件中的值 -->
    <div id="app">
      num:{{num}}
      <!-- v-model后面没有属性名(随便定义)  则update后面要加默认属性名:model-value 实现双向数据绑定 -->
      <ds v-model="num"></ds>
    </div>
  </body>
  <script>
    let app = Vue.createApp({
      data() {
        return {
          num: 1,
        };
      },
    });
    // 定义组件
    app.component("ds", {
      props: [],
      data() {
        return {
          a: 1,
        };
      },
      template: `
        <button @click="add">a:{{a}}</button>
      `,
      methods: {
        add() {
          this.a++;
          this.$emit("update:model-value", this.a);
        },
      },
    });
    app.mount("#app");
  </script>

五、Vuex

Vuex 是一个状态管理库,它提供了一种集中式存储管理应用的所有组件所需的数据和状态的方式。

// store.js
import { createStore } from 'vuex';

const store = createStore({
  state() {
    return {
      message: 'initial message'
    };
  },
  mutations: {
    updateMessage(state, message) {
      state.message = message;
    }
  }
});

export default store;

// 发送事件的组件
import { mapMutations } from 'vuex';

export default {
  methods: {
    ...mapMutations(['updateMessage']),
    sendMessage() {
      this.updateMessage('data from sender');
    }
  }
};

// 接收事件的组件
import { mapState } from 'vuex';

export default {
  computed: {
    ...mapState(['message'])
  }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Woli美美啊

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

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

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

打赏作者

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

抵扣说明:

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

余额充值