# 组件通信

# 父组件获取子组件信息的方式

# 1. ref

# 2. props

	// 父组件通过props给子组件传入一个事件
	<div class="school-container">
    <h1>school name:{{ schoolName }}</h1>
    <h1>school address:{{ address }}</h1>
    <StudentModel :getStudentName="getStudentName" ref="child"></StudentModel>
    <h1 class="stu" v-if="studentName">{{ studentName }}</h1>
  </div>
	……
	……
	  methods: {
    getStudentName(stuName) {
      if (!this.studentName) this.studentName = stuName;
    },
  // 子组件中直接执行事件,将父组件需要的数据当成实惨传入
	<div class="student-container">
    <h2>student name:{{ name }}</h2>
    <h2>student sex:{{ sex }}</h2>
    <h2>student age:{{ age }}</h2>
    <button @click="getStudentName(name)">click</button>
  </div>
	……
	……
	  props: {
      getStudentName:Function
		}

# 3.$emit(自定义事件)

在Vue.js中,$emit是一个实例方法,用于子组件向父组件发送事件。父组件可以使用v-on指令(或它的简写@)来监听这些事件。通常,我们使用$emit来传递子组件的数据或通知事件发生。下面是在子组件中使用$emit的一个例子: 假设你有一个名为StudentModel的子组件,当点击按钮时,你希望通知父组件学生的名字。在子组件中,你会这样使用$emit:

<!-- StudentModel.vue -->
<template>
  <div class="student-container">
    <h2>student name: {{ name }}</h2>
    <!-- 其他代码 -->
    <button @click="notifyStudentName">click</button>
  </div>
</template>
<script>
export default {
  name: "StudentModel",
  props: {
    // props定义
  },
  data() {
    return {
      name: '学生的名字'
      // ...
    };
  },
  methods: {
    notifyStudentName() {
      this.$emit('studentNameChanged', this.name);
    }
  }
  // ...
};
</script>

在上面的代码中,当按钮被点击时,notifyStudentName方法被调用,它会执行this.$emit,其中studentNameChanged是事件名称,this.name是要发送给父组件的数据。 然后,在父组件中,你可以这样监听这个事件:

<!-- 父组件 -->
<template>
  <div>
    <student-model @studentNameChanged="getStudentName"></student-model>
    <!-- 其他代码 -->
  </div>
</template>
<script>
import StudentModel from './StudentModel.vue';
export default {
  components: {
    StudentModel
  },
  methods: {
    getStudentName(name) {
      console.log("学生的名字是:", name);
      // 这里你可以执行更多相关的操作
    }
  }
  // ...
};
</script>

在这个父组件模板中,@studentNameChanged 是监听子组件发出的 studentNameChanged 事件,并将其关联到父组件的 getStudentName 方法,name 参数将包含从子组件传递的值。如此一来,子组件就能够与父组件通信,并且父组件能够根据触发的事件执行相应的操作。

适用于子组件需要通知父组件其内部发生的变化,常伴随用户交互。

# vue2.0的事件绑定和解绑:

// 绑定一个名为 'my-event' 的事件监听器
this.$on('my-event', this.myEventHandler);
// 稍后,解绑这个事件监听器
this.$off('my-event', this.myEventHandler);
// 在 Vue 3.0 中,$on,$off 和 $once 实例方法被移除了,建议使用函数式的事件监听模式。
  1. 首先,创建一个可以作为中央事件总线的Vue实例:

    // event-bus.js
    import Vue from 'vue';
    export const EventBus = new Vue();
    

    接下来,在你的组件中,你可以导入这个事件总线并使用它来发射和监听事件。以下是如何在组件中实现的示例:

    // ComponentA.vue
    <template>
      <button @click="sendEvent">Send Event</button>
    </template>
    <script>
    import { EventBus } from './event-bus.js';
    export default {
      methods: {
        sendEvent() {
          // 发射事件及附带的数据,事件名随意起
          EventBus.$emit('my-event', { message: 'Hello from Component A!' });
        }
      }
    };
    </script>
    

    然后,在另一个组件中监听这个事件:

    // ComponentB.vue
    <template>
      <div v-if="message">{{ message }}</div>
    </template>
    <script>
    import { EventBus } from './event-bus.js';
    export default {
      data() {
        return {
          message: ''
        };
      },
      created() {
        // 监听事件,并用传递的数据更新本地数据
        EventBus.$on('my-event', data => {
          this.message = data.message;
        });
      },
      beforeDestroy() {
        // 组件销毁前,确保移除事件监听,防止内存泄漏
        EventBus.$off('my-event');
      }
    };
    </script>
    

# $emit,$on,$off

  • $emit: 用来触发一个事件。这通常用于子组件想要通知父组件某件事情发生了。它接受第一个参数为事件的名称,之后的参数为传递给事件处理函数的参数。
// 子组件中
this.$emit('my-event', 'hello', { some: 'data' });
  • $on: 用来监听一个事件。你可以在组件的createdmounted钩子中设置监听器,来处理其他组件发射的事件。
// 父组件中
this.$on('my-event', (message, obj) => {
  console.log(message); // 输出 'hello'
  console.log(obj); // 输出 { some: 'data' }
});
  • $off: 用来移除事件监听器。当你不再需要监听某个事件,或者组件要被销毁时,应该移除监听器以防止内存泄漏。
// 离开组件前或不需要监听时
this.$off('my-event');

# 父子通信和兄弟通信的区别:

  • 父子:父组件挂一个事件到子标签上,并给出时间触发时的回调函数;子:安排事件如何触发(如 click),用 emit 发射事件,并传出数据给父组建;
  • 兄弟:发送方需用事件巴士 emit 一个事件(事件名随意起),并附上需要传递的数据;收信方需要在 create 阶段用事件巴士 on 通信的事件名,在beforeDestory 阶段用事件巴士 off 事件。