0
点赞
收藏
分享

微信扫一扫

海外发稿:大舍传媒-媒体宣发Vents Magazine女性杂志展现独特魅力与价值

vue3学习记录-组件通信

1.父子组件通信

父组件:

<template>
  父组件原有的title:{{ title }}
  <p>---</p>
  <com :title="title" :flag="true" @changeTitle="changeTitle"></com>
</template>

<script setup>
import { computed, ref } from 'vue'
import com from './components/com.vue'
let title = ref('我是标题')
function changeTitle(newTitle){
  title.value = newTitle
}
</script>

<style></style>

子组件:

<template>
    <div>
        我是子组件
        <p>子组件的title:{{ title }}</p>
        <button @click="changeTitle1">我要给父组件传参</button>
    </div>
</template>

<script setup>
defineProps({
    title: {
        default: '',
        type: String
    },
    flag: Boolean
})
const emit1 = defineEmits(['changeTitle'])
function changeTitle1() {
    emit1('changeTitle', '我是子组件传给父组件的参数')
}

//子传父事件 
//1.const emit1 = defineEmits(['changeTitle'])定义emit
//2.直接在事件后 emit1('changeTitle', '我是子组件传给父组件的参数'),然后父组件接收

</script>

<style lang="scss" scoped></style>

defineProps父传子定义,defineEmits子传父定义

2.兄弟组件传值

2.1 以父组件为媒介

//App.vue
<script setup>
import A from './components/A.vue';
import B from './components/B.vue';
import { ref } from 'vue';
const mainFlag = ref(false)
const clickEvent1 = (val) => {
  mainFlag.value = val
  console.log('clickEvent', val);
};
</script>


<template>
  <A @clickEvent="clickEvent1"></A>
  <B :mainFlag="mainFlag"></B>
</template>

<style scoped></style>

//A.vue
<template>
  <div class="container">
    <p>我是A组件
    </p>
    <el-button @click="clickEvent1">分发事件</el-button>
  </div>
  </template>
  
  <script setup>
  import { ref, reactive} from 'vue'
  const flag = ref(false)
  const clickEvent1 = () =>{
    flag.value =!flag.value
    emit1('clickEvent',flag.value)
  }
  const emit1 = defineEmits(['clickEvent'])
  </script>
  <style lang='scss' scoped>
  .container{
      width: 200px;
      height: 200px;
      background-color: lightcoral;
      margin-bottom: 10px;
  }
  </style>
//B.vue
<template>
  <div class="container">
      <p>我是B组件</p>
      {{ mainFlag }}
  </div>
</template>

<script setup>
import { ref, reactive } from 'vue'
defineProps({
  mainFlag: {
      type: Boolean,
      required: true
  }
})

</script>
<style lang='scss' scoped>
.container {
  width: 200px;
  height: 200px;
  background-color: lightblue;
}
</style>

A组件分发事件给父组件,父组件再把值传给B组件。这样是可以的,但是写法不太简易,层级多了就要递传。

2.2 发布订阅模式

// eventBus.js

class EventBus {
    constructor() {
        this.events = new Map();
    }

    // 订阅事件
    on(eventName, callback) {
        if (!this.events.has(eventName)) {
            this.events.set(eventName, []);
        }
        this.events.get(eventName).push(callback);
    }

    // 取消订阅
    off(eventName, callback) {
        if (!this.events.has(eventName)) return;
        const callbacks = this.events.get(eventName);
        const index = callbacks.indexOf(callback);
        if (index !== -1) {
            callbacks.splice(index, 1);
        }
    }

    // 发布事件
    emit(eventName, ...args) {
       const callbacks = this.events.get(eventName) || [];
       callbacks.forEach(callback => callback(...args));
    }
}

export default new EventBus();

2.3 使用mitt

安装依赖

2.3.1 全局使用

//main.js
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import mitt from 'mitt'

const emitter = mitt()

const app = createApp(App)
app.config.globalProperties.$EventBus = emitter

app.mount('#app')

<!-- ComponentA.vue -->
<script setup>
import { ref,getCurrentInstance } from 'vue'
const message = ref('')
const { proxy } = getCurrentInstance()
const sendMessage2 = () => {
  proxy.$EventBus.emit('new-message', message.value)
  message.value = ''
}
onBeforeUnmount(() =>{
  proxy.$EventBus.off('new-message')
})
</script>
<template>
  <div>
    <input v-model="message" placeholder="输入消息" />
    <button @click="sendMessage2">发送消息2</button>
  </div>
</template>

<!-- ComponentB.vue -->
<script setup>
import { ref, onMounted, onUnmounted,getCurrentInstance } from 'vue'
const receivedMessages = ref([])
const {proxy} = getCurrentInstance()

const onNewMessage = (msg) => {
  receivedMessages.value.push(msg)
}
onMounted(() => {
  proxy.$EventBus.on('new-message', onNewMessage)
})
onUnmounted(() => {
  proxy.$EventBus.off('new-message', onNewMessage)
})
</script>
<template>
  <div>
    <h2>接收到的消息:</h2>
    <ul>
      <li v-for="(msg, index) in receivedMessages" :key="index">{{ msg }}</li>
    </ul>
  </div>
</template>

2.3.2 局部使用

// eventBus.js
import { ref } from 'vue'
import mitt from 'mitt'

const emitter = mitt()
const bus = ref(emitter)

export default bus

<!-- ComponentA.vue -->
<script setup>
import { ref, getCurrentInstance, onBeforeUnmount } from 'vue'
import bus from '../eventBus'

const message = ref('')
const { proxy } = getCurrentInstance()

const sendMessage = () => {
  bus.value.emit('new-message', message.value)
  message.value = ''
}

const sendMessage2 = () => {
  proxy.$EventBus.emit('new-message', message.value)
  message.value = ''
}
onBeforeUnmount(
  () => {
    proxy.$EventBus.off('new-message')
    bus.value.off('new-message')
  }
)

</script>

<template>
  <div>
    <input v-model="message" placeholder="输入消息" />
    <button @click="sendMessage">发送消息</button>
    <button @click="sendMessage2">发送消息2</button>
  </div>
</template>

<!-- ComponentB.vue -->
<script setup>
import { ref, onMounted, onUnmounted,getCurrentInstance } from 'vue'
import bus from '../eventBus'

const receivedMessages = ref([])
const {proxy} = getCurrentInstance()

const onNewMessage = (msg) => {
  receivedMessages.value.push(msg)
}

onMounted(() => {
  proxy.$EventBus.on('new-message', onNewMessage)
  bus.value.on('new-message', onNewMessage)
})

onUnmounted(() => {
  proxy.$EventBus.off('new-message', onNewMessage)
  bus.value.off('new-message', onNewMessage)
})
</script>

<template>
  <div>
    <h2>接收到的消息:</h2>
    <ul>
      <li v-for="(msg, index) in receivedMessages" :key="index">{{ msg }}</li>
    </ul>
  </div>
</template>

其实试了下,两个都可以一起用。
在这里插入图片描述

举报

相关推荐

0 条评论