dcloudio / uni-app

A cross-platform framework using Vue.js
https://uniapp.dcloud.io
Apache License 2.0
40.08k stars 3.64k forks source link

vue3 - 小程序 getCurrentInstance().value?.ctx.$children 始终存在销毁节点,导致其length不断增多 #5143

Open dongjinc opened 1 month ago

dongjinc commented 1 month ago

1.发生了什么 instance.value?.ctx.$children 始终存在销毁节点,导致其length不断增多 ex:

<NhForm>
  <NhField></NhField>
  <NhField></NhField>
  <NhField v-if=“条件判断”></NhField>
</NhForm>
<script setup lang="ts">
defineOptions({
  name: "NhForm",
});
const instance = ref(null);

onMounted(() => {
  instance.value = getCurrentInstance();
});

const nhFormRef = ref(null);

// const nhFormInstance = getCurrentInstance();
const validate = () => {
  return new Promise((resolve, reject) => {
    console.log(instance.value?.ctx.$parent.$children.length, 'nhFormRef')
    if (!!instance.value?.ctx.$children.length) {
      const hasInValid = instance.value?.ctx.$children.filter((item: any) => !item.validate());
      resolve(!hasInValid.length);
    } else {
      resolve(true);
    }
  });
};

defineExpose({
  validate,
});
</script>

<template>
  <form class="nh-form" id="id">
    <template>
      <slot /> 
    </template>
  </form>
</template>

通过 instance.value?.ctx.$children 获取 当前 slot 插槽渲染的组件,如果渲染组件时,内有条件组件,会导致这个 children.length 不断增加,比如当前实际3个节点,内部因条件事件导致出现了5个节点,销毁的节点也在。

期望: instance.value?.ctx.$children 移除销毁节点;

{
    endMeasure(instance, `init`);
  }
  {
    if (options.parentComponent && instance.proxy) {
     // 具体源码问题出现在这里, 只有push,没有移除操作。
      options.parentComponent.ctx.$children.push(getExposeProxy(instance) || instance.proxy);
    }
  }
  setupRenderEffect(instance);
  {
    popWarningContext();
    endMeasure(instance, `mount`);
  }
bfc846958672 commented 1 month ago

已确认bug,下个版本修复。 非常不推荐使用$children api, 这个api 在vue3语法内是没有的,是uniapp内部特殊添加的。你这个需求应该可以通过 provide,inject api来解决

dongjinc commented 1 month ago

已确认bug,下个版本修复。 非常不推荐使用$children api, 这个api 在vue3语法内是没有的,是uniapp内部特殊添加的。你这个需求应该可以通过 provide,inject api来解决

好的,后面我再改造一下,非常感谢