uniapp中父组件向子组件传递prop时,如果prop是对象,对象内部不能包含function属性
例子如下
father.vue
<template>
<view class="uni-container">
<child :fatherData="fatherData" :fatherFcuntion="fatherFcuntion" :fatherMethod="fatherMethod"></child>
</view>
</template>
<script>
import child from './child.vue'
export default {
components: {
child
},
data() {
return {
fatherData: {
a: 1,
b: {
isShow: function() {
console.log("data定义对象属性函数");
}
}
},
fatherFcuntion: function() {
console.log("data定义函数变量");
},
}
},
methods: {
fatherMethod() {
console.log("method的定义函数");
},
}
}
</script>
child.vue
<template>
<view>
child
</view>
</template>
<script>
export default({
name: "child",
props: {
fatherData: {
type: Object,
default: function() {
return {};
}
},
fatherFunction: {
type: Function,
default: function() {
return function() {}
}
},
fatherMethod: {
type: Function,
default: function() {
return function() {}
}
}
},
mounted() {
console.log("父组件data定义的变量包含函数", this.fatherData);
console.log("父组件data定义的函数变量", this.fatherFunction);
console.log("父组件method定义的函数", this.fatherMethod);
}
})
</script>
结果
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200702173033111.png
可以看到展示数据
1.data定义的变量包含函数,函数属性直接被删除了
2.data定义的函数变量,可以正常传递
3.method定义的函数,可以正常传递
总结:uniapp的prop传递的变量为对象时,对象内部含有函数属性,该函数属性会直接被删除
Vue中的测试截图
Vue中是可以正常传递
原因
uniapp中父组件进行初始化时,会经过
initMixin(Vue);
stateMixin(Vue);
eventsMixin(Vue);
lifecycleMixin(Vue);
renderMixin(Vue);
在initMixIn(Vue)中会执行
function initMixin (Vue) {
Vue.prototype._init = function (options) {
.......
if (vm.$options.el) {
vm.$mount(vm.$options.el);
}
};
}
_init方法中的$mount函数如下
// public mount method
Vue.prototype.$mount = function(
el ,
hydrating
) {
return mountComponent$1(this, el, hydrating)
};
mountComponent$1函数如下,会new Watcher,函数为updateComponent,函数updateComponent会执行_update
function mountComponent$1(
vm,
el,
hydrating
) {
..........
var updateComponent = function () {
vm._update(vm._render(), hydrating);
};
// we set this to vm._watcher inside the watcher's constructor
// since the watcher's initial patch may call $forceUpdate (e.g. inside child
// component's mounted hook), which relies on vm._watcher being already defined
new Watcher(vm, updateComponent, noop, {
before: function before() {
if (vm._isMounted && !vm._isDestroyed) {
callHook(vm, 'beforeUpdate');
}
}
}, true /* isRenderWatcher */);
hydrating = false;
return vm
}
在lifecycleMixin函数内部会定义一个_update属性函数
Vue.prototype._update = function (vnode, hydrating) {
.......
if (!prevVnode) {
// initial render
vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false /* removeOnly */);
} else {
// updates
vm.$el = vm.__patch__(prevVnode, vnode);
}
......
};
_update函数中有一个__patch__函数,主要比较newData与oldData的差异进行差量更新
var patch = function(oldVnode, vnode) {
............
if (this.mpType === 'page' || this.mpType === 'component') {
var mpInstance = this.$scope;
var data = Object.create(null);
try {
data = cloneWithData(this);
} catch (err) {
console.error(err);
}
data.__webviewId__ = mpInstance.data.__webviewId__;
var mpData = Object.create(null);
Object.keys(data).forEach(function (key) { //仅同步 data 中有的数据
mpData[key] = mpInstance.data[key];
});
var diffData = this.$shouldDiffData === false ? data : diff(data, mpData);
..........
};
上述有一个cloneWithData方法,最后会返回深度克隆的值,但是该方法会有问题,丢失value值为function的key,并且可能存在循环依赖问题。
function cloneWithData(vm) {
.....
return JSON.parse(JSON.stringify(ret))
}
上述可以看到,使用cloneWithData采用了JSON.parse(JSON.stringify(ret)),导致this中的data中会识别到对象如果包含function,会直接丢失到该属性,并且diff算法会识别到b:{}的差异,直接影响到子组件。