1. // 闭包存储的值
    2. // dep 值的观察者集合
    3. // getter/setter 值原先具有的 get/set
    4. // val 传入的初始化值,或者原先的值,如果值默认带有 getter,但没有 setter 则为 undefined
    5. // childOb 如果值还有子集合且当前环境支持深度挟持,则为子集的 observe
    6. export function defineReactive (
    7. obj: Object,
    8. key: string,
    9. val: any,
    10. customSetter?: ?Function,
    11. shallow?: boolean
    12. ) {
    13. // 初始化依赖项,闭包存储
    14. const dep = new Dep()
    15. // 如果该值无法被修改则直接 return,configurable 代表这个值是否能被改变
    16. const property = Object.getOwnPropertyDescriptor(obj, key)
    17. if (property && property.configurable === false) {
    18. return
    19. }
    20. // 获取该值上原有的 getter/setter,防止被覆盖导致失效,闭包存储
    21. const getter = property && property.get
    22. const setter = property && property.set
    23. // (!getter || setter) 当有自定义 getter 并且没有 setter 的时候不对其进行深度响应式,
    24. // 与下面 set 中的 if (getter && !setter) return 呼应。
    25. // 没有传 val 则手动获取
    26. if ((!getter || setter) && arguments.length === 2) {
    27. val = obj[key]
    28. }
    29. // 如说是非深度响应式则值响应到这一层,反之默认向下递归,非深度响应式比如 $attrs、$listeners
    30. // childOb 是指向的子集的 __ob__,主要用于 $set/$delete
    31. let childOb = !shallow && observe(val) // 递归 observe
    32. Object.defineProperty(obj, key, {
    33. enumerable: true,
    34. configurable: true,
    35. get: function reactiveGetter () {
    36. // 获取该获取的值
    37. const value = getter ? getter.call(obj) : val
    38. // 如果当前有观察者,则将其加入到依赖项中
    39. // 同时如果有子集,则给其同时添加依赖项
    40. // 如果当前值是数组,则将依赖深度的添加到每一个子数组中,因为默认其实是依赖了数组内的每一层
    41. if (Dep.target) {
    42. dep.depend()
    43. if (childOb) {
    44. childOb.dep.depend()
    45. if (Array.isArray(value)) {
    46. dependArray(value)
    47. }
    48. }
    49. }
    50. return value
    51. },
    52. set: function reactiveSetter (newVal) {
    53. // 获取原先的值
    54. const value = getter ? getter.call(obj) : val
    55. // 如果值没有发生实际变化或者前后值都为 NaN,则直接返回,不触发依赖更新(|| 后面的判断是为了兼容 NaN !== NaN 的情况)
    56. if (newVal === value || (newVal !== newVal && value !== value)) {
    57. return
    58. }
    59. // 如果在非生产且有自定义 setter,则触发,因为自定义 setter 往往是非法报错之类的信息,所以仅在非生产执行。
    60. if (process.env.NODE_ENV !== 'production' && customSetter) {
    61. customSetter()
    62. }
    63. // 只读的值不进行值的修改,开发者给一个值只设置了 getter,没设置 setter 的时候
    64. // #7981: for accessor properties without setter
    65. if (getter && !setter) return
    66. // 如果有自定义 setter,则使用自定义 set,反之用默认的方式修改值
    67. if (setter) {
    68. setter.call(obj, newVal)
    69. } else {
    70. val = newVal
    71. }
    72. // 深度响应式的情况下,如果重新赋了一个新的子集则重新使其具备响应式
    73. childOb = !shallow && observe(newVal)
    74. // 通知依赖项
    75. dep.notify()
    76. }
    77. })
    78. }