dcloudio / dcloudio/uni-app

vue3 微信小程序解构插槽内组件生命周期异常

Open
#5,066 4 comments 0 reactions 0 assignees View on GitHub
不明确 vue版本或者运行平台
Dominant language
JavaScript
Stars
41.6k
Forks
3.7k
Avg merge
7h 6m
Merged PRs (30d)
6

Description

您好!
1. 我在编写一个依赖插槽内的事件的组件,对插槽内容暴露了回调函数。下面提供了示例 `TestComp`
2. 在使用该组件的地方,将该回调函数放到 image 组件的 `@load` 事件上,由此,`TestComp` 能够知道何时插槽内的图像加载完成。
3. 在列表刷新时,由于 `key` 变化,已有的组件被卸载,随后装载新组件。出现 bug 的地方在于,若列表内的图片没有更新,触发 load 的会是已被卸载的组件,而非新装载的组件。为了模拟列表没有更新的情况,下面的示例中的 `list` 是不变的。

控制台输出:(红线即为刷新的位置,通过点击下面示例页面内的刷新按钮触发)
image

可以看到,已经被卸载的组件,再次触发了一次 load。而新装载的组件没有触发 load。

一些猜想和疑惑
1. load 触发错位不禁让我猜想,会不会只是触发的函数没有及时被替换,但在本地进一步的测试发现,当 `list` 有 10 张图,有且只有第 3 张发生了改变,那么依然会触发第 3 张图片对应的已被卸载的组件的 load,然后,在新图加载好后,再触发一次新装载组件的 load,即,触发了 11 次 load。
2. 因此我又猜想,这里面可能有两个问题,一个是被卸载后的组件会莫名触发一次 load,一个是新加载的图片由于被缓存不会触发 load。但更进一步的测试发现,在其他情况下,已加载的同路径图片,总是仍会触发 load 的。

由于原本组件的一些逻辑非常复杂且似乎相关,这个问题已经困扰了我很久,才梳理简化到这个示例,希望开发者大佬们能帮忙解决问题,有时间精力的话希望能解答下原理疑惑,感谢!

版本:3.0.0-4020420240722002

```vue

import { onMounted, onUnmounted } from 'vue';

const {
itemKey,
} = defineProps({
itemKey: {
type: Number,
},
});

onMounted(() => {
console.log('mounted', itemKey);
});

onUnmounted(() => {
console.log('unmounted', itemKey);
});

const onLoad = () => {
console.log('load', itemKey);
};

const onError = () => {
console.log('error', itemKey);
};

```

```vue

import { ref } from 'vue';
import TestComp from './test-comp.vue';

const refreshId = ref(0);
const getKey = (index) => refreshId.value * 100 + index;
const list = Array(3).fill('https://picsum.photos/100');


刷新



.img {
width: 300rpx;
height: 300rpx;
}

```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.