dcloudio / dcloudio/uni-app

动态渲染(computed)表单组件时使用了插槽导致渲染报错componentUpdateScopedSlotsFn函数不够严谨

Open
#5,917 1 comment 0 reactions 1 assignee Claimed by @chouchouji View on GitHub
Dominant language
JavaScript
Stars
41.6k
Forks
3.7k
Avg merge
7h 6m
Merged PRs (30d)
6

Description

### 发行方式

小程序

### 具体平台

微信小程序开发者工具 真机 1.06.2504010

### 开发环境

macOS

### 项目创建方式

CLI命令行

### Vue 版本

vue3

### 依赖版本

"@dcloudio/uni-app": "3.0.0-alpha-4080720251125001",
"@dcloudio/uni-app-harmony": "3.0.0-alpha-4080720251125001",
"@dcloudio/uni-app-plus": "3.0.0-alpha-4080720251125001",
"@dcloudio/uni-components": "3.0.0-alpha-4080720251125001",
"@dcloudio/uni-h5": "3.0.0-alpha-4080720251125001",
"@dcloudio/uni-mp-alipay": "3.0.0-alpha-4080720251125001",
"@dcloudio/uni-mp-baidu": "3.0.0-alpha-4080720251125001",
"@dcloudio/uni-mp-harmony": "3.0.0-alpha-4080720251125001",
"@dcloudio/uni-mp-jd": "3.0.0-alpha-4080720251125001",
"@dcloudio/uni-mp-kuaishou": "3.0.0-alpha-4080720251125001",
"@dcloudio/uni-mp-lark": "3.0.0-alpha-4080720251125001",
"@dcloudio/uni-mp-qq": "3.0.0-alpha-4080720251125001",
"@dcloudio/uni-mp-toutiao": "3.0.0-alpha-4080720251125001",
"@dcloudio/uni-mp-weixin": "3.0.0-alpha-4080720251125001",
"@dcloudio/uni-mp-xhs": "3.0.0-alpha-4080720251125001",
"@dcloudio/uni-quickapp-webview": "3.0.0-alpha-4080720251125001",

### 问题描述

错误如下
```js
TypeError: Cannot read property '0' of null
at vendor.js? [sm]:5093
at Array.forEach ()
at Object.componentUpdateScopedSlotsFn (vendor.js? [sm]:5090)
at callWithErrorHandling (vendor.js? [sm]:1949)
at flushJobs (vendor.js? [sm]:2153)(env: macOS,mp,1.06.2504010; lib: 3.8.9)
```

原函数处理为
```js
function componentUpdateScopedSlotsFn() {
const scopedSlotsData = this.$scopedSlotsData;
if (!scopedSlotsData || scopedSlotsData.length === 0) {
return;
}
const start = Date.now();
const mpInstance = this.ctx.$scope;
const oldData = mpInstance.data;
const diffData = /* @__PURE__ */ Object.create(null);
scopedSlotsData.forEach(({ path, index, data }) => {
const oldScopedSlotData = getValueByDataPath(oldData, path);
const diffPath = isString(index) ? `${path}.${index}` : `${path}[${index}]`;
if (typeof oldScopedSlotData === "undefined" || typeof oldScopedSlotData[index] === "undefined") {
diffData[diffPath] = data;
} else {
const diffScopedSlotData = diff(
data,
oldScopedSlotData[index]
);
Object.keys(diffScopedSlotData).forEach((name) => {
diffData[diffPath + "." + name] = diffScopedSlotData[name];
});
}
});
scopedSlotsData.length = 0;
if (Object.keys(diffData).length) {
if (process.env.UNI_DEBUG) {
console.log(
"uni-app:[" + +/* @__PURE__ */ new Date() + "][" + (mpInstance.is || mpInstance.route) + "][" + this.uid + "][\u8017\u65F6" + (Date.now() - start) + "]\u4F5C\u7528\u57DF\u63D2\u69FD\u5DEE\u91CF\u66F4\u65B0",
JSON.stringify(diffData)
);
}
mpInstance.setData(diffData);
}
}
```

判断oldScopedSlotData值时 未处理oldScopedSlotData为null的情况 导致报错 可以将
```js
if (typeof oldScopedSlotData === "undefined" || typeof oldScopedSlotData[index] === "undefined") {
```
改为
```js
if (typeof oldScopedSlotData === "undefined" || oldScopedSlotData === null || typeof oldScopedSlotData[index2] === "undefined") {
```

### 重现步骤

可以创建一个表单 渲染数据使用computed进行动态计算 渲染时使用两层slot插入动态渲染时就会出现
```vue





```
其中DynamicRenderer为根据类型渲染的表单渲染器。

当在外部改变list的某个依赖值 比如外部传入的数据动态改变后 本应该显示5个变成3个。来回切换一次就能复现出这个bug

### 期望行为

期望正常渲染不报错

### 实际行为

_No response_

### 截图或录屏

Image

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.