Vue响应式原理实现

 Vue响应式特点

1.使用对象时, 必须先声明, 这个属性才是响应式的

2. 给对象数据递归增加 getter和setter 

 3. 数组里套对象, 对象时支持响应式变化的,常量则没有效果

4. 修改数组的索引及长度, 是不会导致视图更新

5. 如果是新增的数据(对象类型), vue 才会帮你监控

vue 要监听的数据 可能是对象, 数组, 或者 其它基本值

1. 首先 说基本数据

// 创建一个观察者函数

function observer(obj) {
 // 判断obj如果不是对象 或者 是 null, 就直接返回
  if (typeof obj !== "object" || typeof obj == null) {
    return obj
  }
 // 判断数据是不是数组
  if (Array.isArray(obj)) {
    
  } else {
    // 否则 就是对象 
    for (let key in obj) {
       // 该函数只处理数据是对象的情况
      defineReactive(obj, key, obj[key])
    }
  }
}
function defineReactive(obj, key, value) {

}
// 测试 
let data = 10

console.log(observer(data)) // 10

第一步完事, 接着处理判断是对象的情况 , 也就是 defineReactive 函数

function defineReactive(obj, key, value) {
  Object.defineProperty(obj, key, {
    get() {
      return value
    },
    set(newValue) {
      if (value !== newValue) {
        value = newValue
        console.log("数据更新:" + newValue)
      }
    }
  })
}
let data = {
  age: 10
}
observer(data)
data.age = 30  // 数据更新:30

接着看这个函数, 现在只是修改 data.age = 30 ,这一层值, 如果是多层对象嵌套, 会发现不会再更新了 ,比如下边这样的

let data = {
  age: {
    id: 10
  }
}
observer(data)
data.age.id = 20

上边的函数,只是处理了第一层数据,会加上 getter, setter,但是多层嵌套后, 并没有增加响应式 

let data = {
  name: "李四",
  age: {
    id: 10
  }
}
observer(data)
data.age.id = 20
data.name = "王参谋"
console.log(data)

但是只更新一次,所以就需要递归处理数据, 也就是说, 新修改的数据 可能是个对象, 第一层遍历后, 它的值也可能是个对象,

所以需要在两个地方都递归调用 observer( ) 函数

递归后

function defineReactive(obj, key, value) {
  observer(value) // 递归处理函数
  Object.defineProperty(obj, key, {
    get() {
      return value
    },
    set(newValue) {
      if (value !== newValue) {
        value = newValue
        observer(value) // 递归函数
        console.log("数据更新:" + newValue)
      }
    }
  })
}
let data = {
  name: "李四",
  age: {
    id: 10
  }
}
observer(data)
data.age.id = 20
data.name = "王参谋"
console.log(data);
console.log(data.age);

可以看到,递归后, 给所有的对象都添加了setter 和 getter

接着处理 如果传入的值是数组...

发布了63 篇原创文章 · 获赞 100 · 访问量 31万+

猜你喜欢

转载自blog.csdn.net/qq_36407748/article/details/102786000