Vue如何监听嵌套组件事件?无需扩展VDatePicker监听子组件input事件
Great question! I’ve run into a similar situation with Vuetify’s date picker components before, so let’s walk through two reliable ways to listen to the VDatePickerDateTable’s input event without modifying or extending the parent VDatePicker component.
Option 1: Listen to the Native DOM Input Event
This approach targets the underlying DOM element of VDatePickerDateTable and listens for its native input event. It’s straightforward but depends on Vuetify’s DOM structure (which is generally stable across minor versions).
<template> <v-date-picker v-model="selectedDays" multiple ref="datePicker" @input="onDayClick" /> </template> <script> export default { data() { return { selectedDays: [], dateTableInputListener: null }; }, mounted() { // Locate the date table DOM element using a Vuetify-specific class const dateTableElement = this.$refs.datePicker.$el.querySelector('.v-date-picker-table'); if (dateTableElement) { // Define the listener and attach it to the element this.dateTableInputListener = (event) => { console.log('VDatePickerDateTable native input event:', event.target.value); // Add your custom logic here }; dateTableElement.addEventListener('input', this.dateTableInputListener); } }, beforeUnmount() { // Clean up the listener to prevent memory leaks const dateTableElement = this.$refs.datePicker.$el.querySelector('.v-date-picker-table'); if (dateTableElement && this.dateTableInputListener) { dateTableElement.removeEventListener('input', this.dateTableInputListener); } }, methods: { onDayClick(data) { console.log('VDatePicker input event:', data); // ["2019-01-01", "2019-01-02", "2019-01-06"] } } }; </script>
Option 2: Listen to the Component's Custom input Event
This method directly targets the VDatePickerDateTable component instance (instead of the DOM) and listens to its custom Vue input event. It’s more aligned with Vue’s component model and less dependent on DOM structure.
<template> <v-date-picker v-model="selectedDays" multiple ref="datePicker" @input="onDayClick" /> </template> <script> export default { data() { return { selectedDays: [], dateTableComponentListener: null }; }, mounted() { // Find the VDatePickerDateTable instance among the parent's children const dateTableComponent = this.$refs.datePicker.$children.find( child => child.$options.name === 'VDatePickerDateTable' ); if (dateTableComponent) { // Listen for the component's custom input event this.dateTableComponentListener = (data) => { console.log('VDatePickerDateTable component input event:', data); // Add your custom logic here }; dateTableComponent.$on('input', this.dateTableComponentListener); } }, beforeUnmount() { // Clean up the listener to prevent memory leaks const dateTableComponent = this.$refs.datePicker.$children.find( child => child.$options.name === 'VDatePickerDateTable' ); if (dateTableComponent && this.dateTableComponentListener) { dateTableComponent.$off('input', this.dateTableComponentListener); } }, methods: { onDayClick(data) { console.log('VDatePicker input event:', data); // ["2019-01-01", "2019-01-02", "2019-01-06"] } } }; </script>
Key Notes
- Option 2 is preferred if you can rely on the component name (
VDatePickerDateTable) staying consistent (Vuetify rarely changes core component names). It’s more "Vue-native" and avoids DOM-related fragility. - For both options, always clean up event listeners in the
beforeUnmounthook to avoid memory leaks in your application. - If you’re using Vuetify 3, double-check the component name or DOM class names—they might differ slightly from Vuetify 2.
内容的提问来源于stack exchange,提问作者izbz

