vue3学习纪录-组件通讯

打印 上一主题 下一主题

主题 1566|帖子 1566|积分 4698

1.父子组件通讯

父组件:
  1. <template>
  2.   父组件原有的title:{{ title }}
  3.   <p>---</p>
  4.   <com :title="title" :flag="true" @changeTitle="changeTitle"></com>
  5. </template>
  6. <script setup>
  7. import { computed, ref } from 'vue'
  8. import com from './components/com.vue'
  9. let title = ref('我是标题')
  10. function changeTitle(newTitle){
  11.   title.value = newTitle
  12. }
  13. </script>
  14. <style></style>
复制代码
子组件:
  1. <template>
  2.     <div>
  3.         我是子组件
  4.         <p>子组件的title:{{ title }}</p>
  5.         <button @click="changeTitle1">我要给父组件传参</button>
  6.     </div>
  7. </template>
  8. <script setup>
  9. defineProps({
  10.     title: {
  11.         default: '',
  12.         type: String
  13.     },
  14.     flag: Boolean
  15. })
  16. const emit1 = defineEmits(['changeTitle'])
  17. function changeTitle1() {
  18.     emit1('changeTitle', '我是子组件传给父组件的参数')
  19. }
  20. //子传父事件
  21. //1.const emit1 = defineEmits(['changeTitle'])定义emit
  22. //2.直接在事件后 emit1('changeTitle', '我是子组件传给父组件的参数'),然后父组件接收
  23. </script>
  24. <style lang="scss" scoped></style>
复制代码
defineProps父传子定义,defineEmits子传父定义
2.兄弟组件传值

2.1 以父组件为媒介

  1. //App.vue
  2. <script setup>
  3. import A from './components/A.vue';
  4. import B from './components/B.vue';
  5. import { ref } from 'vue';
  6. const mainFlag = ref(false)
  7. const clickEvent1 = (val) => {
  8.   mainFlag.value = val
  9.   console.log('clickEvent', val);
  10. };
  11. </script>
  12. <template>
  13.   <A @clickEvent="clickEvent1"></A>
  14.   <B :mainFlag="mainFlag"></B>
  15. </template>
  16. <style scoped></style>
  17. //A.vue
  18. <template>
  19.   <div class="container">
  20.     <p>我是A组件
  21.     </p>
  22.     <el-button @click="clickEvent1">分发事件</el-button>
  23.   </div>
  24.   </template>
  25.   
  26.   <script setup>
  27.   import { ref, reactive} from 'vue'
  28.   const flag = ref(false)
  29.   const clickEvent1 = () =>{
  30.     flag.value =!flag.value
  31.     emit1('clickEvent',flag.value)
  32.   }
  33.   const emit1 = defineEmits(['clickEvent'])
  34.   </script>
  35.   <style lang='scss' scoped>
  36.   .container{
  37.       width: 200px;
  38.       height: 200px;
  39.       background-color: lightcoral;
  40.       margin-bottom: 10px;
  41.   }
  42.   </style>
  43. //B.vue
  44. <template>
  45.   <div class="container">
  46.       <p>我是B组件</p>
  47.       {{ mainFlag }}
  48.   </div>
  49. </template>
  50. <script setup>
  51. import { ref, reactive } from 'vue'
  52. defineProps({
  53.   mainFlag: {
  54.       type: Boolean,
  55.       required: true
  56.   }
  57. })
  58. </script>
  59. <style lang='scss' scoped>
  60. .container {
  61.   width: 200px;
  62.   height: 200px;
  63.   background-color: lightblue;
  64. }
  65. </style>
复制代码
A组件分发事件给父组件,父组件再把值传给B组件。这样是可以的,但是写法不太浅易,层级多了就要递传。
2.2 发布订阅模式

  1. // eventBus.js
  2. class EventBus {
  3.     constructor() {
  4.         this.events = new Map();
  5.     }
  6.     // 订阅事件
  7.     on(eventName, callback) {
  8.         if (!this.events.has(eventName)) {
  9.             this.events.set(eventName, []);
  10.         }
  11.         this.events.get(eventName).push(callback);
  12.     }
  13.     // 取消订阅
  14.     off(eventName, callback) {
  15.         if (!this.events.has(eventName)) return;
  16.         const callbacks = this.events.get(eventName);
  17.         const index = callbacks.indexOf(callback);
  18.         if (index !== -1) {
  19.             callbacks.splice(index, 1);
  20.         }
  21.     }
  22.     // 发布事件
  23.     emit(eventName, ...args) {
  24.        const callbacks = this.events.get(eventName) || [];
  25.        callbacks.forEach(callback => callback(...args));
  26.     }
  27. }
  28. export default new EventBus();
复制代码
2.3 使用mitt

安装依靠
   npm install mitt
  2.3.1 全局使用

  1. //main.js
  2. import { createApp } from 'vue'
  3. import './style.css'
  4. import App from './App.vue'
  5. import mitt from 'mitt'
  6. const emitter = mitt()
  7. const app = createApp(App)
  8. app.config.globalProperties.$EventBus = emitter
  9. app.mount('#app')
  10. <!-- ComponentA.vue -->
  11. <script setup>
  12. import { ref,getCurrentInstance } from 'vue'
  13. const message = ref('')
  14. const { proxy } = getCurrentInstance()
  15. const sendMessage2 = () => {
  16.   proxy.$EventBus.emit('new-message', message.value)
  17.   message.value = ''
  18. }
  19. onBeforeUnmount(() =>{
  20.   proxy.$EventBus.off('new-message')
  21. })
  22. </script>
  23. <template>
  24.   <div>
  25.     <input v-model="message" placeholder="输入消息" />
  26.     <button @click="sendMessage2">发送消息2</button>
  27.   </div>
  28. </template>
  29. <!-- ComponentB.vue -->
  30. <script setup>
  31. import { ref, onMounted, onUnmounted,getCurrentInstance } from 'vue'
  32. const receivedMessages = ref([])
  33. const {proxy} = getCurrentInstance()
  34. const onNewMessage = (msg) => {
  35.   receivedMessages.value.push(msg)
  36. }
  37. onMounted(() => {
  38.   proxy.$EventBus.on('new-message', onNewMessage)
  39. })
  40. onUnmounted(() => {
  41.   proxy.$EventBus.off('new-message', onNewMessage)
  42. })
  43. </script>
  44. <template>
  45.   <div>
  46.     <h2>接收到的消息:</h2>
  47.     <ul>
  48.       <li v-for="(msg, index) in receivedMessages" :key="index">{{ msg }}</li>
  49.     </ul>
  50.   </div>
  51. </template>
复制代码
2.3.2 局部使用

  1. // eventBus.js
  2. import { ref } from 'vue'
  3. import mitt from 'mitt'
  4. const emitter = mitt()
  5. const bus = ref(emitter)
  6. export default bus
  7. <!-- ComponentA.vue -->
  8. <script setup>
  9. import { ref, getCurrentInstance, onBeforeUnmount } from 'vue'
  10. import bus from '../eventBus'
  11. const message = ref('')
  12. const { proxy } = getCurrentInstance()
  13. const sendMessage = () => {
  14.   bus.value.emit('new-message', message.value)
  15.   message.value = ''
  16. }
  17. const sendMessage2 = () => {
  18.   proxy.$EventBus.emit('new-message', message.value)
  19.   message.value = ''
  20. }
  21. onBeforeUnmount(
  22.   () => {
  23.     proxy.$EventBus.off('new-message')
  24.     bus.value.off('new-message')
  25.   }
  26. )
  27. </script>
  28. <template>
  29.   <div>
  30.     <input v-model="message" placeholder="输入消息" />
  31.     <button @click="sendMessage">发送消息</button>
  32.     <button @click="sendMessage2">发送消息2</button>
  33.   </div>
  34. </template>
  35. <!-- ComponentB.vue -->
  36. <script setup>
  37. import { ref, onMounted, onUnmounted,getCurrentInstance } from 'vue'
  38. import bus from '../eventBus'
  39. const receivedMessages = ref([])
  40. const {proxy} = getCurrentInstance()
  41. const onNewMessage = (msg) => {
  42.   receivedMessages.value.push(msg)
  43. }
  44. onMounted(() => {
  45.   proxy.$EventBus.on('new-message', onNewMessage)
  46.   bus.value.on('new-message', onNewMessage)
  47. })
  48. onUnmounted(() => {
  49.   proxy.$EventBus.off('new-message', onNewMessage)
  50.   bus.value.off('new-message', onNewMessage)
  51. })
  52. </script>
  53. <template>
  54.   <div>
  55.     <h2>接收到的消息:</h2>
  56.     <ul>
  57.       <li v-for="(msg, index) in receivedMessages" :key="index">{{ msg }}</li>
  58.     </ul>
  59.   </div>
  60. </template>
复制代码
其实试了下,两个都可以一起用。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

tsx81429

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表