uni-app 父组件向子组件传递propbug

eit6fx6z  于 2021-11-27  发布在  Java
关注(0)|答案(5)|浏览(436)

问题描述

当父组件传递子组件的prop为一个对象时,在父组件修改对象,假设新的porp为newObj,旧的prop为oldObj,如果Object.keys(newObj).length > Object.keys(oldObj).length,会将oldObj存在的属性,newObj不存在的属性,赋予newObj。

父组件修改传入子组件的prop,会触发render更新,进而触发pach打补丁,pach代码中有一段是diff函数,会使oldObj的属性附加到newObj的属性中。

导致错误的打包源代码如下
/packages/vue-cli-plugin-uni/packages/mp-vue/dist/mp.runtime.esm.js的文件中
源码如下如下

//  patch函数中
// data为newData,mpData为oldData
 var diffData = this.$shouldDiffData === false ? data : diff(data, mpData);
// diff函数
function diff(current, pre) {
    var result = {};
    syncKeys(current, pre);
    _diff(current, pre, '', result);
    return result
}
// syncKeys函数
function syncKeys(current, pre) {
    if (current === pre) { return }
    var rootCurrentType = type(current);
    var rootPreType = type(pre);
    if (rootCurrentType == OBJECTTYPE && rootPreType == OBJECTTYPE) {
        if(Object.keys(current).length >= Object.keys(pre).length){
            for (var key in pre) {
                var currentValue = current[key];
               // 如果newObj的keys数量大于oldObj的keys数量,则会将oldObj的属性赋予newObj,并且值为null
                if (currentValue === undefined) {
                    current[key] = null;
                } else {
                    syncKeys(currentValue, pre[key]);
                }
            }
        }
    } else if (rootCurrentType == ARRAYTYPE && rootPreType == ARRAYTYPE) {
        if (current.length >= pre.length) {
            pre.forEach(function (item, index) {
                syncKeys(current[index], item);
            });
        }
    }
}
sulc1iza

sulc1iza1#

有示例工程吗,理论上syncKeys的那处代码不会执行到的,因为执行diff之前,有个前置处理,保证了新旧obj的根属性是一样的
https://github.com/dcloudio/uni-app/blob/dev/packages/vue-cli-plugin-uni/packages/mp-vue/dist/mp.runtime.esm.js#L5640

zkure5ic

zkure5ic2#

https://blog.csdn.net/py_boy/article/details/107189409,可以从这个url看到测试例子,当在父组件修改传向子组件的prop时,会触发。我把代码执行过程截图也发给你,只是截取了一部分,在附件中。 工程我也把我的两个测试组件发给你,父组件father.vue,子组件childTry.vue,在附件中…

------------------ 原始邮件 ------------------ 发件人: "fxy060608"<notifications@github.com>; 发送时间: 2020年7月8日(星期三) 上午9:50 收件人: "dcloudio/uni-app"<uni-app@noreply.github.com>; 抄送: "daifayang"<498108281@qq.com>;"Author"<author@noreply.github.com>; 主题: Re: [dcloudio/uni-app] 父组件向子组件传递propbug (#1882) 有示例工程吗,理论上syncKeys的那处代码不会执行到的,因为执行diff之前,有个前置处理,保证了新旧obj的根属性是一样的 https://github.com/dcloudio/uni-app/blob/dev/packages/vue-cli-plugin-uni/packages/mp-vue/dist/mp.runtime.esm.js#L5640 — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.

pvabu6sv

pvabu6sv3#

确实有此问题
之所以将已不存在的key赋值为null,是因为差量数据更新需要对该key做删除逻辑
该算法,可以解决大部分情况,你这个应该是要循环config之类的吧,可以自己computed过滤一下null值
目前你文章里提到的this.$shouldDiffData开关,暂未对外暴露,不排除后续可能有调整。
举例:
const oldData = {a:1,b:2}
const newData = {a:1,c:2}
console.log(diff(newData,oldData)) // {c: 2, b: null}
// 其中c:2是新增属性,b:null是删除属性

kmynzznz

kmynzznz4#

可以直接在子组件执行this.$shouldDiffData = false,关闭diff算法。能请教下,将已不存在的key赋值为null,是因为差量数据更新对该key做删除逻辑,是指对子组件中的oldData中做删除逻辑吗,如果为了删除逻辑,,能举个正常例子吗?…

------------------ 原始邮件 ------------------ 发件人: "fxy060608"<notifications@github.com>; 发送时间: 2020年7月8日(星期三) 下午2:39 收件人: "dcloudio/uni-app"<uni-app@noreply.github.com>; 抄送: "daifayang"<498108281@qq.com>;"Author"<author@noreply.github.com>; 主题: Re: [dcloudio/uni-app] 父组件向子组件传递propbug (#1882) 确实有此问题 之所以将已不存在的key赋值为null,是因为差量数据更新需要对该key做删除逻辑 该算法,可以解决大部分情况,你这个应该是要循环config之类的吧,可以自己computed过滤一下null值 目前你文章里提到的this.$shouldDiffData开关,暂未对外暴露,不排除后续可能有调整。 举例: const oldData = {a:1,b:2} const newData = {a:1,c:2} console.log(diff(newData,oldData)) // {c: 2, b: null} // 其中c:2是新增属性,b:null是删除属性 — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.

rqcrx0a6

rqcrx0a65#

1.$shouldDiffData这个不是正式对外的属性,不排除后续调整的可能性
2.比如v-if="config.b" ,不设置null的话,那就会影响v-if判断了,这种情况,要么全量更新config,要么就是差量更新config.b=null

相关问题