Vue3组件间的通信方式是什么

发布时间:2023-04-25 15:21:09 作者:iii
来源:亿速云 阅读:169

Vue3组件间的通信方式是什么

在Vue.js 3中,组件是构建用户界面的基本单元。随着应用规模的扩大,组件之间的通信变得尤为重要。Vue3提供了多种组件间通信的方式,每种方式都有其适用的场景和优缺点。本文将详细介绍Vue3中组件间通信的各种方式,并通过示例代码帮助读者更好地理解和应用这些方法。

1. Props 和 Events

1.1 Props

Props是Vue中最常用的父子组件通信方式。父组件通过props向子组件传递数据,子组件通过props接收数据。

示例代码

<!-- ParentComponent.vue -->
<template>
  <div>
    <ChildComponent :message="parentMessage" />
  </div>
</template>

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

export default {
  components: {
    ChildComponent
  },
  data() {
    return {
      parentMessage: 'Hello from Parent'
    };
  }
};
</script>

<!-- ChildComponent.vue -->
<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  props: {
    message: {
      type: String,
      required: true
    }
  }
};
</script>

1.2 Events

子组件可以通过$emit方法触发事件,父组件通过监听这些事件来响应子组件的动作。

示例代码

<!-- ParentComponent.vue -->
<template>
  <div>
    <ChildComponent @notify="handleNotify" />
  </div>
</template>

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

export default {
  components: {
    ChildComponent
  },
  methods: {
    handleNotify(message) {
      alert(message);
    }
  }
};
</script>

<!-- ChildComponent.vue -->
<template>
  <div>
    <button @click="notifyParent">Notify Parent</button>
  </div>
</template>

<script>
export default {
  methods: {
    notifyParent() {
      this.$emit('notify', 'Hello from Child');
    }
  }
};
</script>

2. Provide 和 Inject

provideinject是Vue3中用于跨层级组件通信的一种方式。父组件通过provide提供数据,子组件通过inject注入数据。

示例代码

<!-- ParentComponent.vue -->
<template>
  <div>
    <ChildComponent />
  </div>
</template>

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

export default {
  components: {
    ChildComponent
  },
  provide() {
    return {
      message: 'Hello from Parent'
    };
  }
};
</script>

<!-- ChildComponent.vue -->
<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

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

3. Vuex

Vuex是Vue.js的官方状态管理库,适用于大型应用中多个组件共享状态的场景。Vuex通过集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

示例代码

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

export default createStore({
  state: {
    message: 'Hello from Vuex'
  },
  mutations: {
    setMessage(state, message) {
      state.message = message;
    }
  },
  actions: {
    updateMessage({ commit }, message) {
      commit('setMessage', message);
    }
  },
  getters: {
    message: state => state.message
  }
});
<!-- ParentComponent.vue -->
<template>
  <div>
    <ChildComponent />
  </div>
</template>

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

export default {
  components: {
    ChildComponent
  }
};
</script>

<!-- ChildComponent.vue -->
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="updateMessage">Update Message</button>
  </div>
</template>

<script>
import { mapGetters, mapActions } from 'vuex';

export default {
  computed: {
    ...mapGetters(['message'])
  },
  methods: {
    ...mapActions(['updateMessage'])
  }
};
</script>

4. Event Bus

Event Bus是一种全局事件总线,适用于非父子组件之间的通信。通过创建一个全局的Vue实例作为事件总线,组件可以通过$on$emit方法进行事件的监听和触发。

示例代码

// eventBus.js
import { createApp } from 'vue';

export const eventBus = createApp({});
<!-- ComponentA.vue -->
<template>
  <div>
    <button @click="sendMessage">Send Message</button>
  </div>
</template>

<script>
import { eventBus } from './eventBus';

export default {
  methods: {
    sendMessage() {
      eventBus.$emit('message', 'Hello from Component A');
    }
  }
};
</script>

<!-- ComponentB.vue -->
<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script>
import { eventBus } from './eventBus';

export default {
  data() {
    return {
      message: ''
    };
  },
  created() {
    eventBus.$on('message', message => {
      this.message = message;
    });
  }
};
</script>

5. Refs 和 $refs

ref$refs是Vue中用于直接访问子组件或DOM元素的一种方式。通过ref属性,父组件可以获取子组件的引用,并直接调用子组件的方法或访问其属性。

示例代码

<!-- ParentComponent.vue -->
<template>
  <div>
    <ChildComponent ref="child" />
    <button @click="callChildMethod">Call Child Method</button>
  </div>
</template>

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

export default {
  components: {
    ChildComponent
  },
  methods: {
    callChildMethod() {
      this.$refs.child.childMethod();
    }
  }
};
</script>

<!-- ChildComponent.vue -->
<template>
  <div>
    <p>Child Component</p>
  </div>
</template>

<script>
export default {
  methods: {
    childMethod() {
      alert('Child Method Called');
    }
  }
};
</script>

6. \(attrs 和 \)listeners

$attrs$listeners是Vue中用于传递属性和事件的机制。$attrs包含了父组件传递给子组件的所有非props属性,而$listeners包含了父组件传递给子组件的所有事件监听器。

示例代码

<!-- ParentComponent.vue -->
<template>
  <div>
    <ChildComponent :custom-attr="customValue" @custom-event="handleCustomEvent" />
  </div>
</template>

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

export default {
  components: {
    ChildComponent
  },
  data() {
    return {
      customValue: 'Custom Value'
    };
  },
  methods: {
    handleCustomEvent() {
      alert('Custom Event Triggered');
    }
  }
};
</script>

<!-- ChildComponent.vue -->
<template>
  <div>
    <p>{{ $attrs['custom-attr'] }}</p>
    <button @click="$listeners['custom-event']">Trigger Custom Event</button>
  </div>
</template>

<script>
export default {
  inheritAttrs: false
};
</script>

7. Composition API

Vue3引入了Composition API,提供了一种更灵活的方式来组织和复用组件逻辑。通过setup函数,组件可以更灵活地管理状态和逻辑。

示例代码

<!-- ParentComponent.vue -->
<template>
  <div>
    <ChildComponent :message="message" @update-message="updateMessage" />
  </div>
</template>

<script>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  setup() {
    const message = ref('Hello from Parent');

    const updateMessage = newMessage => {
      message.value = newMessage;
    };

    return {
      message,
      updateMessage
    };
  }
};
</script>

<!-- ChildComponent.vue -->
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="updateMessage">Update Message</button>
  </div>
</template>

<script>
export default {
  props: {
    message: {
      type: String,
      required: true
    }
  },
  setup(props, { emit }) {
    const updateMessage = () => {
      emit('update-message', 'Hello from Child');
    };

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

8. Teleport

<teleport>是Vue3中新增的一个特性,允许将组件的内容渲染到DOM中的任意位置。这在处理模态框、弹出框等场景时非常有用。

示例代码

<!-- ParentComponent.vue -->
<template>
  <div>
    <button @click="showModal = true">Show Modal</button>
    <teleport to="body">
      <ModalComponent v-if="showModal" @close="showModal = false" />
    </teleport>
  </div>
</template>

<script>
import { ref } from 'vue';
import ModalComponent from './ModalComponent.vue';

export default {
  components: {
    ModalComponent
  },
  setup() {
    const showModal = ref(false);

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

<!-- ModalComponent.vue -->
<template>
  <div class="modal">
    <p>This is a modal</p>
    <button @click="$emit('close')">Close</button>
  </div>
</template>

<script>
export default {
  emits: ['close']
};
</script>

<style scoped>
.modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: white;
  padding: 20px;
  border: 1px solid #ccc;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
</style>

9. Suspense

<suspense>是Vue3中用于处理异步组件加载的特性。它允许在异步组件加载完成之前显示一个备用内容。

示例代码

<!-- ParentComponent.vue -->
<template>
  <div>
    <Suspense>
      <template #default>
        <AsyncComponent />
      </template>
      <template #fallback>
        <p>Loading...</p>
      </template>
    </Suspense>
  </div>
</template>

<script>
import { defineAsyncComponent } from 'vue';

const AsyncComponent = defineAsyncComponent(() =>
  import('./AsyncComponent.vue')
);

export default {
  components: {
    AsyncComponent
  }
};
</script>

<!-- AsyncComponent.vue -->
<template>
  <div>
    <p>Async Component Loaded</p>
  </div>
</template>

<script>
export default {
  async setup() {
    await new Promise(resolve => setTimeout(resolve, 2000));
  }
};
</script>

10. 自定义指令

自定义指令是Vue中用于直接操作DOM的一种方式。通过自定义指令,可以在组件中封装一些通用的DOM操作逻辑。

示例代码

<!-- ParentComponent.vue -->
<template>
  <div>
    <p v-highlight="'yellow'">This text will be highlighted</p>
  </div>
</template>

<script>
export default {
  directives: {
    highlight: {
      mounted(el, binding) {
        el.style.backgroundColor = binding.value;
      }
    }
  }
};
</script>

11. 插槽(Slots)

插槽是Vue中用于组件内容分发的一种机制。通过插槽,父组件可以将内容插入到子组件的指定位置。

示例代码

<!-- ParentComponent.vue -->
<template>
  <div>
    <ChildComponent>
      <template #header>
        <h1>Header Content</h1>
      </template>
      <template #default>
        <p>Default Content</p>
      </template>
      <template #footer>
        <p>Footer Content</p>
      </template>
    </ChildComponent>
  </div>
</template>

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

export default {
  components: {
    ChildComponent
  }
};
</script>

<!-- ChildComponent.vue -->
<template>
  <div>
    <header>
      <slot name="header"></slot>
    </header>
    <main>
      <slot></slot>
    </main>
    <footer>
      <slot name="footer"></slot>
    </footer>
  </div>
</template>

<script>
export default {};
</script>

12. 作用域插槽(Scoped Slots)

作用域插槽允许子组件将数据传递给父组件,父组件可以根据这些数据渲染内容。

示例代码

<!-- ParentComponent.vue -->
<template>
  <div>
    <ChildComponent v-slot="{ user }">
      <p>{{ user.name }}</p>
    </ChildComponent>
  </div>
</template>

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

export default {
  components: {
    ChildComponent
  }
};
</script>

<!-- ChildComponent.vue -->
<template>
  <div>
    <slot :user="user"></slot>
  </div>
</template>

<script>
export default {
  data() {
    return {
      user: {
        name: 'John Doe'
      }
    };
  }
};
</script>

13. 动态组件

动态组件允许在运行时动态切换组件。通过<component>元素和is属性,可以根据条件渲染不同的组件。

示例代码

<!-- ParentComponent.vue -->
<template>
  <div>
    <button @click="currentComponent = 'ComponentA'">Show Component A</button>
    <button @click="currentComponent = 'ComponentB'">Show Component B</button>
    <component :is="currentComponent" />
  </div>
</template>

<script>
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';

export default {
  components: {
    ComponentA,
    ComponentB
  },
  data() {
    return {
      currentComponent: 'ComponentA'
    };
  }
};
</script>

<!-- ComponentA.vue -->
<template>
  <div>
    <p>Component A</p>
  </div>
</template>

<script>
export default {};
</script>

<!-- ComponentB.vue -->
<template>
  <div>
    <p>Component B</p>
  </div>
</template>

<script>
export default {};
</script>

14. 异步组件

异步组件允许在需要时延迟加载组件。通过defineAsyncComponent函数,可以定义一个异步组件,并在组件加载完成之前显示一个备用内容。

示例代码

<!-- ParentComponent.vue -->
<template>
  <div>
    <Suspense>
      <template #default>
        <AsyncComponent />
      </template>
      <template #fallback>
        <p>Loading...</p>
      </template>
    </Suspense>
  </div>
</template>

<script>
import { defineAsyncComponent } from 'vue';

const AsyncComponent = defineAsyncComponent(() =>
  import('./AsyncComponent.vue')
);

export default {
  components: {
    AsyncComponent
  }
};
</script>

<!-- AsyncComponent.vue -->
<template>
  <div>
    <p>Async Component Loaded</p>
  </div>
</template>

<script>
export default {
  async setup() {
    await new Promise(resolve => setTimeout(resolve, 2000));
  }
};
</script>

15. 自定义事件

自定义事件是Vue中用于组件间通信的一种方式。通过$emit方法,子组件可以触发自定义事件,父组件通过监听这些事件来响应子组件的动作。

示例代码

<!-- ParentComponent.vue -->
<template>
  <div>
    <ChildComponent @custom-event="handleCustomEvent" />
  </div>
</template>

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

export default {
  components: {
    ChildComponent
  },
  methods: {
    handleCustomEvent(message) {
      alert(message);
    }
  }
};
</script>

<!-- ChildComponent.vue -->
<template>
  <div>
    <button @click="triggerEvent">Trigger Event</button>
  </div>
</template>

<script>
export default {
  methods: {
    triggerEvent() {
      this.$emit('custom-event', 'Hello from Child');
    }
  }
};
</script>

16. 全局事件总线

全局事件总线是一种全局的事件通信机制,适用于非父子组件之间的通信。通过创建一个全局的Vue实例作为事件总线,组件可以通过$on$emit方法进行事件的监听和触发。

示例代码

// eventBus.js
import { createApp } from 'vue';

export const eventBus = createApp({});
<!-- ComponentA.vue -->
<template>
  <div>
    <button @click="sendMessage">Send Message</button>
  </div>
</template>

<script>
import { eventBus } from './eventBus';

export default {
  methods: {
    sendMessage() {
      eventBus.$emit('message', 'Hello from Component A');
    }
  }
};
</script>

<!-- ComponentB.vue -->
<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script>
import { eventBus } from './eventBus';

export default {
  data() {
    return {
      message: ''
    };
  },
  created() {
    eventBus.$on('message', message => {
      this.message = message;
    });
  }
};
</script>

17. 状态管理库(如Pinia)

Pinia是Vue3中推荐的状态管理库,它提供了更简洁和灵活的状态管理方式。与Vuex相比,Pinia更加轻量级且易于使用。

示例代码

”`javascript // store.js import { defineStore } from ‘pinia’;

export const useMessageStore = defineStore(‘message’, { state: () =>

推荐阅读:
  1. 怎么掌握Vue3完整知识体系
  2. Vue3父子组件间通信、组件间双向绑定的方法

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

vue3

上一篇:vue3页面加载完成后怎么获取宽度、高度

下一篇:vue3+vite2+mqtt连接遇到的坑怎么解决

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》