1.9 watch选项合并

在使用Vue进行开发时,我们有时需要自定义侦听器来响应数据的变化,当需要在数据变化时执行异步或者开销较大的操作时,watch往往是高效的。对于 watch 选项的合并处理,它类似于生命周期钩子,只要父选项有相同的观测字段,则和子的选项合并为数组,在监测字段改变时同时执行父类选项的监听代码。处理方式和生命钩子选项的区别在于,生命周期钩子选项必须是函数,而watch选项最终在合并的数组中可以是包含选项的对象,也可以是对应的回调函数,或者方法名。

  1. strats.watch = function (parentVal,childVal,vm,key) {
  2. //火狐浏览器在Object的原型上拥有watch方法,这里对这一现象做了兼容
  3. // var nativeWatch = ({}).watch;
  4. if (parentVal === nativeWatch) { parentVal = undefined; }
  5. if (childVal === nativeWatch) { childVal = undefined; }
  6. // 没有子,则默认用父选项
  7. if (!childVal) { return Object.create(parentVal || null) }
  8. {
  9. // 保证watch选项是一个对象
  10. assertObjectType(key, childVal, vm);
  11. }
  12. // 没有父则直接用子选项
  13. if (!parentVal) { return childVal }
  14. var ret = {};
  15. extend(ret, parentVal);
  16. for (var key$1 in childVal) {
  17. var parent = ret[key$1];
  18. var child = childVal[key$1];
  19. // 父的选项先转换成数组
  20. if (parent && !Array.isArray(parent)) {
  21. parent = [parent];
  22. }
  23. ret[key$1] = parent
  24. ? parent.concat(child)
  25. : Array.isArray(child) ? child : [child];
  26. }
  27. return ret
  28. };

下面结合具体的例子看合并结果:

  1. var Parent = Vue.extend({
  2. watch: {
  3. 'test': function() {
  4. console.log('parent change')
  5. }
  6. }
  7. })
  8. var Child = Parent.extend({
  9. watch: {
  10. 'test': {
  11. handler: function() {
  12. console.log('child change')
  13. }
  14. }
  15. },
  16. data() {
  17. return {
  18. test: 1
  19. }
  20. }
  21. })
  22. var vm = new Child().$mount('#app');
  23. vm.test = 2;
  24. // 输出结果
  25. parent change
  26. child change

简单总结一下:对于watch选项的合并,最终和父类选项合并成数组,并且数组的选项成员,可以是回调函数,选项对象,或者函数名。