Vue中的组件通信

发布于:2024-06-16 ⋅ 阅读:(20) ⋅ 点赞:(0)

父向子通信

1.定义props

子组件中,定义期望接收的属性。例如,在子组件的script部分:

export default {
  props: {
    message: String // 假设父组件要传递一个字符串类型的数据
  }
}

2.传递数据

在父组件的模板中,通过属性绑定的方式将数据传递给子组件。

<template>
  <ChildComponent :message="parentMessage" />
</template>

 这里parentMessage是父组件的数据属性,:message是将该数据绑定到子组件的message prop上。

子向父通信

1.触发事件

在子组件中,当需要通知父组件时,可以使用this.$emit触发一个自定义事件,并可附带参数。

methods: {
  sendDataToParent() {
    this.$emit('child-event', { someData: 'Hello from child!' });
  }
}

2.监听事件

在父组件的模板中,使用v-on或简写@来监听子组件触发的事件,并定义处理函数。

<template>
  <ChildComponent @child-event="handleChildEvent" />
</template>

<script>
export default {
  methods: {
    handleChildEvent(childData) {
      console.log('Received data from child:', childData);
    }
  }
}
</script>

当子组件触发child-event时,父组件的handleChildEvent方法会被调用,并接收到子组件传递的数据

通过v-model简化代码

通过v-model,父组件可以直接绑定一个变量到子组件的输入值,而不需要显式地定义事件监听器或处理函数来更新数据。子组件通过监听内部的变动并发出input事件,维持了这种双向绑定关系.

//父组件
<template>
  <div>
    <base-select v-model="selectedCity"></base-select>
  </div>
</template>

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

export default {
  components: {
    BaseSelect
  },
  data() {
    return {
      selectedCity: '' // 这个变量将与BaseSelect组件的选择值双向绑定
    };
  }
};
</script>
//子组件
<template>
  <select :value="value" @change="handleChange">
    <!-- 选项列表 -->
  </select>
</template>

<script>
export default {
  props: {
    value: String // 用来接收v-model绑定的值
  },
  methods: {
    handleChange(e) {
      this.$emit('input', e.target.value); // 当下拉选项变化时,触发input事件并传递新值
    }
  }
};
</script>

注意

  • 单向数据流: Vue推荐数据流动主要遵循单向数据流原则,即数据从父组件流向子组件,通过事件回调进行反向通信,保持数据流向的清晰。
  • 避免直接修改Props: 子组件不应该直接修改接收到的props,如果需要修改数据,应该通过触发事件让父组件去处理。如果确实需要局部状态,可以使用子组件的本地数据。

事件总线 

1.创建Event Bus实例

创建一个Vue实例作为事件总线。这个实例并不用于渲染任何内容,而是纯粹作为事件的中心枢纽

import Vue from 'vue';
export const EventBus = new Vue();

2.发送事件(发布)

在发送事件的组件中,使用EventBus.$emit方法触发一个事件,并可以传递数据。

// 在某个组件中
import { EventBus } from './eventBus.js';

methods: {
  sendMessage() {
    EventBus.$emit('messageSent', { text: 'Hello from sender!' });
  }
}

3.监听事件(订阅)

需要接收事件的组件中,使用EventBus.$on方法监听特定事件。

// 在另一个组件中
import { EventBus } from './eventBus.js';

mounted() {
  EventBus.$on('messageSent', this.receiveMessage);
},
beforeDestroy() {
  // 为了避免内存泄漏,记得在组件销毁前移除事件监听器
  EventBus.$off('messageSent', this.receiveMessage);
},
methods: {
  receiveMessage(payload) {
    console.log('Received message:', payload.text);
  }
}

注意

  • 内存泄漏:由于事件监听器可能长期存在,务必在组件卸载时使用EventBus.$off移除不再需要的监听器,以防止内存泄漏。
  • 代码可维护性:随着应用复杂度增加,过度依赖Event Bus可能导致代码难以理解和维护。对于大型应用,可能需要转向使用Vuex这样的状态管理库来更系统地管理状态和事件。
  • 替代方案:Vue 3引入了Composition API,可以通过创建自定义组合API或使用第三方库如pinia来实现更灵活的状态管理和跨组件通信,减少对Event Bus的依赖。

祖先向后代通信

1.在祖先组件中使用 provide

祖先组件中使用 provide 来提供数据或方法。provide 接收一个对象或返回对象的函数,这个对象的属性将被注入到后代组件中。

// AncestorComponent.vue
export default {
  provide() {
    return {
      message: 'Hello from ancestor',
      someMethod() {
        console.log('This method is provided by ancestor.');
      }
    };
  }
};

2. 在后代组件中使用 inject

后代组件使用 inject 来接收这些提供的数据或方法。可以直接注入具体的键名,或者提供一个对象来配置注入行为。

// DescendantComponent.vue
export default {
  inject: ['message', 'someMethod'],
  created() {
    console.log(this.message); // 输出: Hello from ancestor
    this.someMethod(); // 输出: This method is provided by ancestor.
  }
};

或者使用对象形式进行更详细的配置:

export default {
  inject: {
    message: { from: 'message' }, // "from" 指定了要注入的属性名
    anotherNameForSomeMethod: { from: 'someMethod' } // 甚至可以重命名注入的属性
  },
  created() {
    console.log(this.message); 
    this.anotherNameForSomeMethod(); 
  }
};

 注意

  • 层级限制provide 和 inject 只能在组件树的后代中生效,不能跳过中间层获取数据。
  • 适用场景:这种方式适用于那些深层次嵌套或不确定层次关系的组件间通信,比如主题切换、全局配置等。
  • 替代方案:对于复杂的应用,考虑使用 Vuex 状态管理模式,它能更高效、清晰地管理全局状态。

网站公告

今日签到

点亮在社区的每一天
去签到