自学内容网 自学内容网

VScode插件:前端每日一题

Vue 如何监听一个插槽的变化?

在 Vue 中,插槽(slot)内容的变化可以通过监听插槽内容所依赖的状态变化来间接实现。如果需要直接监听插槽内容的变化,Vue 并未提供内置的直接事件机制,但可以通过以下方法实现。


方法 1:使用 key 强制更新

如果插槽内容依赖于某个动态值变化,可以给插槽的父组件提供一个动态 key。当插槽内容发生变化时,更新 key 来强制重新渲染插槽组件。

示例

<template>
  <ChildComponent :key="slotKey">
    <template #default>
      <div>{{ slotContent }}</div>
    </template>
  </ChildComponent>
  <button @click="updateSlotContent">Update Slot</button>
</template>

<script>
export default {
  data() {
    return {
      slotContent: 'Initial Slot Content',
      slotKey: 0, // 用于强制刷新
    };
  },
  methods: {
    updateSlotContent() {
      this.slotContent = 'Updated Slot Content';
      this.slotKey += 1; // 更新 key
    },
  },
};
</script>

方法 2:利用 watch 监听插槽相关的依赖数据

插槽内容通常依赖父组件的数据,监听这些数据的变化可以间接检测插槽内容的变化。

示例

<template>
  <ChildComponent>
    <template #default>
      <div>{{ slotContent }}</div>
    </template>
  </ChildComponent>
  <button @click="updateSlotContent">Update Slot</button>
</template>

<script>
export default {
  data() {
    return {
      slotContent: 'Initial Slot Content',
    };
  },
  methods: {
    updateSlotContent() {
      this.slotContent = 'Updated Slot Content';
    },
  },
  watch: {
    slotContent(newVal) {
      console.log('Slot content changed:', newVal);
    },
  },
};
</script>

方法 3:使用子组件的 $slot.default()

如果需要在子组件中检测插槽内容的变化,可以使用 Vue 3 的 $slots.default() 函数或依赖注入。

示例

<template>
  <div>
    <slot></slot>
  </div>
</template>

<script>
export default {
  updated() {
    // 在组件更新时检测插槽内容的变化
    console.log('Slot content updated:', this.$slots.default?.());
  },
};
</script>

方法 4:通过事件通知

父组件在数据变化时,主动通过事件通知子组件插槽内容发生了变化。

示例

父组件

<template>
  <ChildComponent @slot-changed="handleSlotChange">
    <template #default>
      <div>{{ slotContent }}</div>
    </template>
  </ChildComponent>
  <button @click="updateSlotContent">Update Slot</button>
</template>

<script>
export default {
  data() {
    return {
      slotContent: 'Initial Slot Content',
    };
  },
  methods: {
    updateSlotContent() {
      this.slotContent = 'Updated Slot Content';
      this.$emit('slot-changed');
    },
    handleSlotChange() {
      console.log('Slot content changed');
    },
  },
};
</script>

子组件

<template>
  <div>
    <slot></slot>
  </div>
</template>

方法 5:MutationObserver(更底层监听 DOM)

如果插槽内容完全是动态的,且需要在 DOM 层面检测变化,可以使用浏览器原生的 MutationObserver

示例

<template>
  <div ref="slotContainer">
    <slot></slot>
  </div>
</template>

<script>
export default {
  mounted() {
    const observer = new MutationObserver(() => {
      console.log('Slot content changed');
    });

    observer.observe(this.$refs.slotContainer, { childList: true, subtree: true });
  },
  beforeUnmount() {
    if (this.observer) {
      this.observer.disconnect();
    }
  },
};
</script>

总结

选择方法时需要根据需求场景来决定:

  1. 如果插槽内容依赖父组件数据,watchkey 是最简单的实现方式。
  2. 如果需要监听插槽内容的 DOM 变化,MutationObserver 是更底层的方法。
  3. 如果插槽内容复杂且动态变化,使用事件通知可以更清晰地管理状态。

原文地址:https://blog.csdn.net/p_s_p/article/details/143846662

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!