关于合并配置的一个问题(续)

来源:3-8 生命周期

FDirector

2019-06-27

老师,还是上一个问题,回复不能输入代码所以另开了一个,您看:
假如这样的一个情景:

let extendObj = {
  updated:function(){
	  console.log("我是扩展的updated")
  },
  methods: {
	  add(){
	      console.log("我是扩展出来的ADD方法")
	  }
  },
}

let app = new Vue({
	el: '#app',
	methods:{
	    add(){
	        console.log("我是原生的ADD方法");      
	    }
	},
	updated() {
	    console.log("我是原生的updated");// 
	},
	extends:extendObj
})

递归执行mergeOptions后得到的新的parent类似于这样:

parent: {
	components: {},
	directives: {},
	filters: {},
	_base: Vue,
	// ......
	updated:function(){
	  console.log("我是扩展的updated")
  	},
    methods: {
	  add(){
	      console.log("我是扩展出来的ADD方法")
	  }
    }
}

然后调用第一段for,结果是把parent混合在了一个空的{}上,这个{}就是options

for (key in parent) {
    mergeField(key)
}

现在得到的结果类似这样:

options: {
	components: {},
	directives: {},
	filters: {},
	_base: Vue,
	// ......
	updated:function(){
	  console.log("我是扩展的updated")
  	},
    methods: {
	  add(){
	      console.log("我是扩展出来的ADD方法")
	  }
    }
}

然后调用第二段的for:

for (key in child) {
    if (!hasOwn(parent, key)) {
      mergeField(key)
    }
}

此时child是这样的:

child: {
	el: '#app',
	methods:{
	    add(){
	        console.log("我是原生的ADD方法");      
	    }
	},
	updated() {
	    console.log("我是原生的updated");
	},
	extends:extendObj
}

可是child的key——update已经存在于parent的key中,
所以 !hasOwn(parent, key) 返回 false,
mergeField(‘update’)被阻拦了,导致child.update没有得到执行mergeField,
因此无论mergeField对不同键的合并方法如何,child.update都没有获得和options合并的机会。
因此最终返回的options上的update不就是parent上的update,也就是extendObj上的update了么?

写回答

1回答

ustbhuangyi

2019-06-27

你再仔细看 mergeField 的代码
function mergeField (key) {
 const strat = strats[key] || defaultStrat
 options[key] = strat(parent[key], child[key], vm, key)
}
当执行 
for (key in parent) {
   mergeField(key)
}
的时候,如果 key 为 updated 的时候,执行 mergeField
进而执行  options[key] = strat(parent[key], child[key], vm, key),这不就已经合并了 child 了吗?

2
1
FDirector
非常感谢!
2019-06-27
共1条回复

Vue.js 源码深入解析 深入理解Vue实现原理

全方位讲解 Vue.js 源码,进阶高级工程师

4986 学习 · 1038 问题

查看课程