VUE框架组件中通信方式(2)

全局事件总线

全局事件总线可以实现任意组件通信,在vue2中可以根据VM与VC的关系推出全局事件总线。

点击查看全局事件总线代码示例
// main.js

import Vue from 'vue'
import App from './App.vue'

// 创建一个Vue实例作为事件总线
export const eventBus = new Vue()

new Vue({
  render: h => h(App),
}).$mount('#app')

<!-- ChildComponent.vue -->

<template>
  <div>
    <button @click="sendMessage">发送消息</button>
  </div>
</template>

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

export default {
  methods: {
    sendMessage() {
      // 通过事件总线发送消息
      eventBus.$emit('message', 'Hello from ChildComponent')
    }
  }
}
</script>

<!-- ParentComponent.vue -->

<template>
  <div>
    <child-component></child-component>
    <p>{{ receivedMessage }}</p>
  </div>
</template>

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

export default {
  data() {
    return {
      receivedMessage: ''
    }
  },
  mounted() {
    // 通过事件总线监听消息
    eventBus.$on('message', message => {
      this.receivedMessage = message
    })
  }
}
</script>

但是在vue3中没有VUE构造函数,也就没有Vue.prototype以及组合式API没有this写法,那么在VUE3想实现全局事件的总线功能就有点不现实,如果想在Vue3中使用全局事件总线功能。可以使用插件mitt实现。
点击查看代码
//安装:$ npm install --save mitt

//引入mitt插件:mitt一个方法,方法执行会返回bus对象(新建bus.ts文件)
import mitt from 'mitt';
const $bus = mitt();
export default $bus;

//=================================
//父组件代码
<template>
  <div class="box">
    <h1>全局事件总线$bus</h1>
    <hr />
    <div class="container">
      <Child1></Child1>
      <Child2></Child2>
    </div>
  </div>
</template>

<script setup lang="ts">
//引入子组件
import Child1 from "./Child1.vue";
import Child2 from "./Child2.vue";
</script>

//=================================
//child1文件代码
<template>
  <div class="child1">
    <h3>我是子组件1:曹植+{{ ccar }}</h3>
  </div>
</template>

<script setup lang="ts">
import $bus from "../../bus";
//组合式API函数
import { ref,onMounted, type Ref } from "vue";
//组件挂载完毕的时候,当前组件绑定一个事件,接受将来兄弟组件传递的数据
let ccar:Ref = ref("宾利") 
onMounted(() => {
  //第一个参数:即为事件类型  第二个参数:即为事件回调
  $bus.on("car", (car) => {
    console.log(car);
    ccar.value = car
  });
});
</script>

//child2文件代码
<template>
  <div class="child2">
     <h2>我是子组件2:曹丕</h2>
     <button @click="handler">点击我给兄弟送一台法拉利</button>
  </div>
</template>

<script setup lang="ts">
//引入$bus对象
import $bus from '../../bus';
//点击按钮回调
const handler = ()=>{
  $bus.emit('car',{car:"法拉利"});
}
</script>

v-model数据传递

v-model指令:多用于收集表单数据,数据双向绑定
v-model也可以实现组件之间的通信,实现父子组件数据同步的业务

正常逻辑上父与子同步数据,应该是父组件在子组件标签属性上将值传递给子组件,子组件用props接收传递的值,同时在父组件的子组件标签上定义自定义事件,然后在子组件中使用emit函数将数据通过自定义事件传递回父组件。
示例代码如下:

//父组件代码
<template>
<Child :modelValue="money" @update:modelValue="handler"></Child>
</template>

<script setup lang="ts">
import Child from "./Child.vue";
import { ref } from "vue";
let money = ref(10000);
//自定义事件的回调
const handler = (num) => {
  //将来接受子组件传递过来的数据
  money.value = num;
};
</script>

//子组件代码
<template>
  <div class="child">
    <h3>钱数:{{ modelValue }}</h3>
    <button @click="handler">父子组件数据同步</button>
  </div>
</template>

<script setup lang="ts">
//接受props
let props = defineProps(["modelValue"]);
let $emit = defineEmits(['update:modelValue']);
//子组件内部按钮的点击回调
const handler = ()=>{
   //触发自定义事件
   $emit('update:modelValue',props.modelValue+1000);//将数据回传给handler的num中
}
</script>

如果使用v-model来同步父子组件的数据的话,v-model相当于什么?
第一:相当有给子组件传递props[modelValue]
第二:相当于给子组件绑定自定义事件update:modelValue
示例代码如下

//父组件代码
<template>
  <div>
    <h1>v-model:钱数{{ money }}{{pageNo}}{{pageSize}}</h1>
    <input type="text" v-model="info" />
    <hr />
    <!-- props:父亲给儿子数据 -->
    <!-- <Child :modelValue="money" @update:modelValue="handler"></Child> -->
    <!-- 
       v-model组件身上使用
       第一:相当有给子组件传递props[modelValue] = 10000
       第二:相当于给子组件绑定自定义事件update:modelValue
     -->
    <Child v-model="money"></Child>
    <hr />
    <Child1 v-model:pageNo="pageNo" v-model:pageSize="pageSize"></Child1>
  </div>
</template>

<script setup lang="ts">
//v-model指令:收集表单数据,数据双向绑定
//v-model也可以实现组件之间的通信,实现父子组件数据同步的业务
//父亲给子组件数据 props
//子组件给父组件数据 自定义事件
//引入子组件
import Child from "./Child.vue";
import Child1 from "./Child1.vue";
import { ref } from "vue";
let info = ref("");
//父组件的数据钱数
let money = ref(10000);
//自定义事件的回调
const handler = (num) => {
  //将来接受子组件传递过来的数据
  money.value = num;
};

//父亲的数据
let pageNo = ref(1);
let pageSize = ref(3);
</script>

//===============================
//子组件代码Child文件
<template>
  <div class="child">
    <h3>钱数:{{ modelValue }}</h3>
    <button @click="handler">父子组件数据同步</button>
  </div>
</template>

<script setup lang="ts">
//接受props
let props = defineProps(["modelValue"]);
let $emit = defineEmits(['update:modelValue']);
//子组件内部按钮的点击回调
const handler = ()=>{
   //触发自定义事件
   $emit('update:modelValue',props.modelValue+1000);
}
</script>

//子组件Child1文件
<template>
  <div class="child2">
    <h1>同时绑定多个v-model</h1>
    <button @click="handler">pageNo{{ pageNo }}</button>
    <button @click="$emit('update:pageSize', pageSize + 4)">
      pageSize{{ pageSize }}
    </button>
  </div>
</template>

<script setup lang="ts">
let props = defineProps(["pageNo", "pageSize"]);
let $emit = defineEmits(["update:pageNo", "update:pageSize"]);
//第一个按钮的事件回调
const handler = () => {
  $emit("update:pageNo", props.pageNo + 3);
};
</script>
posted @ 2023-06-27 13:46  林子里的风  阅读(21)  评论(0)    收藏  举报