1、前言理解:

vue 一大特性数据驱动即数据更改驱动视图的变化 所以 数据变化监测是很重要的步骤 实现原理 js的Object.defineProperty 方法

2、观测Object数据 :

  1. Object.defineProperty(obj, params, {
  2. enumerable: true,
  3. configurable: true,
  4. get(){
  5. console.log('price属性被读取了')
  6. return val
  7. },
  8. set(newVal){
  9. console.log('price属性被修改了')
  10. val = newVal
  11. }
  12. })

通过defineProperty 中的set 和 get 可以观测到某个属性的读和写的操作

3、通过递归观测所有的属性

  1. /**
  2. * Observer类会通过递归的方式把一个对象的所有属性都转化成可观测对象
  3. */
  4. export class Observer {
  5. constructor (value) {
  6. this.value = value
  7. // 给value新增一个__ob__属性,值为该value的Observer实例
  8. // 相当于为value打上标记,表示它已经被转化成响应式了,避免重复操作
  9. def(value,'__ob__',this)
  10. if (Array.isArray(value)) {
  11. // 当value为数组时的逻辑
  12. // ...
  13. } else {
  14. this.walk(value)
  15. }
  16. }
  17. walk (obj: Object) {
  18. const keys = Object.keys(obj)
  19. for (let i = 0; i < keys.length; i++) {
  20. defineReactive(obj, keys[i])
  21. }
  22. }
  23. }
  24. /**
  25. * 使一个对象转化成可观测对象
  26. * @param { Object } obj 对象
  27. * @param { String } key 对象的key
  28. * @param { Any } val 对象的某个key的值
  29. */
  30. function defineReactive (obj,key,val) {
  31. // 如果只传了obj和key,那么val = obj[key]
  32. if (arguments.length === 2) {
  33. val = obj[key]
  34. }
  35. if(typeof val === 'object'){
  36. new Observer(val)
  37. }
  38. Object.defineProperty(obj, key, {
  39. enumerable: true,
  40. configurable: true,
  41. get(){
  42. console.log(`${key}属性被读取了`);
  43. return val;
  44. },
  45. set(newVal){
  46. if(val === newVal){
  47. return
  48. }
  49. console.log(`${key}属性被修改了`);
  50. val = newVal;
  51. }
  52. })
  53. }

value新增一个__ob__属性,值为该valueObserver实例。这个操作相当于为value打上标记,表示它已经被转化成响应式了,避免重复操作
然后判断数据的类型,只有object类型的数据才会调用walk将每一个属性转换成getter/setter的形式来侦测变化。 最后,在defineReactive中当传入的属性值还是一个object时使用new observer(val)来递归子属性,这样我们就可以把obj中的所有属性(包括子属性)都转换成getter/seter的形式来侦测变化。 也就是说,只要我们将一个object传到observer中,那么这个object就会变成可观测的、响应式的object