响应式入口

  1. /**
  2. * 两件事:
  3. * 数据响应式的入口:分别处理 props、methods、data、computed、watch
  4. * 优先级:props、methods、data、computed 对象中的属性不能出现重复,优先级和列出顺序一致
  5. * 其中 computed 中的 key 不能和 props、data 中的 key 重复,methods 不影响
  6. */
  7. export function initState (vm: Component) {
  8. vm._watchers = []
  9. const opts = vm.$options
  10. // 处理 props 对象,为 props 对象的每个属性设置响应式,并将其代理到 vm 实例上
  11. if (opts.props) initProps(vm, opts.props)
  12. // 处理 methos 对象,校验每个属性的值是否为函数、和 props 属性比对进行判重处理,最后得到 vm[key] = methods[key]
  13. if (opts.methods) initMethods(vm, opts.methods)
  14. /**
  15. * 做了三件事
  16. * 1、判重处理,data 对象上的属性不能和 props、methods 对象上的属性相同
  17. * 2、代理 data 对象上的属性到 vm 实例
  18. * 3、为 data 对象的上数据设置响应式
  19. */
  20. if (opts.data) {
  21. initData(vm)
  22. } else {
  23. observe(vm._data = {}, true /* asRootData */)
  24. }
  25. /**
  26. * 三件事:
  27. * 1、为 computed[key] 创建 watcher 实例,默认是懒执行
  28. * 2、代理 computed[key] 到 vm 实例
  29. * 3、判重,computed 中的 key 不能和 data、props 中的属性重复
  30. */
  31. if (opts.computed) initComputed(vm, opts.computed)
  32. /**
  33. * 三件事:
  34. * 1、处理 watch 对象
  35. * 2、为 每个 watch.key 创建 watcher 实例,key 和 watcher 实例可能是 一对多 的关系
  36. * 3、如果设置了 immediate,则立即执行 回调函数
  37. */
  38. if (opts.watch && opts.watch !== nativeWatch) {
  39. initWatch(vm, opts.watch)
  40. }
  41. /**
  42. * 其实到这里也能看出,computed 和 watch 在本质是没有区别的,都是通过 watcher 去实现的响应式
  43. * 非要说有区别,那也只是在使用方式上的区别,简单来说:
  44. * 1、watch:适用于当数据变化时执行异步或者开销较大的操作时使用,即需要长时间等待的操作可以放在 watch 中
  45. * 2、computed:其中可以使用异步方法,但是没有任何意义。所以 computed 更适合做一些同步计算
  46. */
  47. }

参考资料

  1. Vue 源码解读(3)—— 响应式原理