例子如下
结果 ; 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:{}的差异,直接影响到子组件。