7.5 initComputed

和上面的分析方法一样,initComputedcomputed数据的初始化,不同之处在于以下几点:

  1. computed可以是对象,也可以是函数,但是对象必须有getter方法,因此如果computed中的属性值是对象时需要进行验证。
  2. 针对computed的每个属性,要创建一个监听的依赖,也就是实例化一个watcher,watcher的定义,可以暂时理解为数据使用的依赖本身,一个watcher实例代表多了一个需要被监听的数据依赖。

除了不同点,initComputed也会将每个属性设置成响应式的数据,同样的,也会对computed的命名做检测,防止与props,data冲突。

  1. function initComputed (vm, computed) {
  2. ···
  3. for (var key in computed) {
  4. var userDef = computed[key];
  5. var getter = typeof userDef === 'function' ? userDef : userDef.get;
  6. // computed属性为对象时,要保证有getter方法
  7. if (getter == null) {
  8. warn(("Getter is missing for computed property \"" + key + "\"."),vm);
  9. }
  10. if (!isSSR) {
  11. // 创建computed watcher
  12. watchers[key] = new Watcher(vm,getter || noop,noop,computedWatcherOptions);
  13. }
  14. if (!(key in vm)) {
  15. // 设置为响应式数据
  16. defineComputed(vm, key, userDef);
  17. } else {
  18. // 不能和props,data命名冲突
  19. if (key in vm.$data) {
  20. warn(("The computed property \"" + key + "\" is already defined in data."), vm);
  21. } else if (vm.$options.props && key in vm.$options.props) {
  22. warn(("The computed property \"" + key + "\" is already defined as a prop."), vm);
  23. }
  24. }
  25. }
  26. }

显然Vue提供了很多种数据供开发者使用,但是分析完后发现每个处理的核心都是将数据转化成响应式数据,有了响应式数据,如何构建一个响应式系统呢?前面提到的watcher又是什么东西?构建响应式系统还需要其他的东西吗?接下来我们尝试着去实现一个极简风的响应式系统。