知道 <slot /> 孩子何时被安装的最简洁的方法是什么?

问题描述 投票:0回答:1

我想在安装我的插槽子项后调用一个函数。

此函数应该替换子元素(使用 GSAP)。我试图在我的

nextTick()
中添加一个
onMounted
但我的函数返回一个错误,说我的孩子还不存在。如果我在调用函数之前添加
setTimeout
,它可以正常工作,但我想避免这种解决方案。

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

<script setup>

const el = ref(null)

onMounted(() => {
    
    const observer = new MutationObserver(() => {
        if (el.value.children.length > 0) {
            observer.disconnect()

            myMethod();
        }
    })
    observer.observe(el.value, { childList: true })
})
</script>

我认为发生这个问题是因为我的子组件有一个 v-if 条件,一旦计算()调用返回,该条件就会设置为 true :

// CHILD COMPONENT
<template>
    <div
        v-if="currentData"
    >
        ...
    </div>
</template>

<script setup>
    const props = defineProps({
        items: { type: Array, default: () => [] },
    });
    const currentData = computed(() => props.items[0]);
</script>

到目前为止,我只能通过使用

MutationObserver()
来获得我想要的东西。

我试图观看该插槽,但我的 console.log 从未被调用过:

// NOT WORKING
const slots = useSlots();
watch(
    () => slots.default(), 
    () => {
        nextTick(() => {
            console.log('test')
        }) 
    }
)

如何使用 nuxt3 方法重构它? 非常感谢你

vue.js vuejs3 nuxt.js nuxtjs3
1个回答
0
投票

在 Vue.js 中,管理有条件渲染的子组件(例如使用基于计算属性的

v-if
指令)确实会给确保在组件完全渲染和安装后执行某些操作带来挑战。在这种情况下,使用
MutationObserver
是有意义的,因为它可以让您直接观察 DOM 中的变化,并在实际安装了条件渲染的插槽内容时做出响应。

这是一种使用 Vue 功能并考虑 Nuxt 3 优化的改进方法,可以在不诉诸

setTimeout
或过度使用
MutationObserver
的情况下处理这种情况。

利用 Vue 的 Reactivity 进行重构

  1. watchEffect
     上使用 
    watch
    currentData
    • 在子组件中,由于
      currentData
      决定内容的渲染,因此您可以为父组件提供一种方法来了解
      currentData
      何时可用。这可以通过发出事件或使用父组件可以监视的反应式
      ref
      来完成。

子组件

<template>
  <div v-if="currentData">
    <!-- Your content here -->
  </div>
</template>

<script setup>
import { defineProps, computed, getCurrentInstance } from 'vue';

const props = defineProps({
    items: { type: Array, default: () => [] },
});

const currentData = computed(() => props.items[0]);

const instance = getCurrentInstance();
watch(currentData, (newVal) => {
  if (newVal) {
    instance.emit('data-ready');
  }
});
</script>

父组件

<template>
  <div ref="el">
    <ChildComponent @data-ready="myMethod" />
  </div>
</template>

<script setup>
import { ref, onMounted, nextTick } from 'vue';
import ChildComponent from './ChildComponent';

const el = ref(null);

const myMethod = () => {
  nextTick(() => {
    // Use GSAP or other manipulations here
    console.log('Child component data is ready, and DOM is updated');
  });
};
</script>

说明:

  • 事件发射:当
    data-ready
    具有真值时,子组件会发射事件
    currentData
    ,表明 DOM 已准备好进行操作。
  • 事件处理:父级监听
    data-ready
    事件并调用
    myMethod
    。此方法使用
    nextTick()
    确保所有 DOM 更新在执行之前已被处理。

此方法的优点:

  • 反应性:利用 Vue 的反应性系统对数据变化做出反应,而不是直接观察 DOM 突变,这可能会降低性能。
  • 解耦:子组件不需要知道父组件将如何处理数据;它只是宣布数据已准备就绪。
  • 可读性和可维护性:这种方式可读性更强,更符合Vue范式,更容易维护和理解。

此重构保持了 Vue 和 Nuxt 的反应性本质,确保对 DOM 的操作仅在满足必要条件后才发生,而不使用超时或过多的 DOM 观察。

© www.soinside.com 2019 - 2024. All rights reserved.