vue2响应式原理

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    // vue2对象响应式原理 Object.defineProperty()
    // vue2数组响应式原理 覆盖可以修改数组的7个方法
    // 从数组原型中获取这7个方法,并覆盖为可以发送更新通知的函数实现
    const originalProto = Array.prototype
    // 克隆数组原型,复制新的原型对象
    const arrayProto = Object.create(originalProto)
    const meArr = ['push','pop','shift','unshift','splice','reverse','sort']
    meArr.forEach(
      method => {
        // 做原型数组方法做的事情
        arrayProto[method] = function(){
          originalProto[method].apply(this,arguments)
          // 通知更新
          notifyUpdate()
        }
      } 
    )

    // 思想: 递归遍历传入obj,定义每个属性的拦截
    function observe(obj){
      if(typeof obj !== 'object' || obj == null){
        return
      }

      // 判断类型,如果是数组就替换他的原型
      if(Array.isArray(obj)){
        Object.setPrototypeOf(obj,arrayProto)
      }else{
        // 拿出对象的key值
        const keys = Object.keys(obj)
        for (let index = 0; index < keys.length; index++) {
          const key = keys[index];
          // 对obj的每个数据进行拦截
          defineReactive(obj,key,obj[key])
        }
      }
    }

    // 具体定义指定的key拦截器
    function defineReactive(obj,key,val){
      // 递归遍历
      observe(val)
      // val实际上是一个闭包
      Object.defineProperty(obj,key,{
        get(){
          return val
        },
        set(newVal){
          if(newVal !== val){
            observe(newVal)
            notifyUpdate()
            val = newVal
          }
        }
      })
    }

    function notifyUpdate(){
      console.log('页面更新');
    }

    const data = {foo:'foo',bar:{a:1},arr:[1,2,3]}
    observe(data)
    // 1普通更新
    // data.foo = 'foooooooo'
    // 2嵌套对象更新
    // data.bar.a = 10
    // 3直接赋值对象
    // data.bar = {a:10}

    // 数组更新
    data.arr.push(4)

    // vue2的问题分析
    // 1需要响应的数据较大时,递归遍历性能不好,消耗较大
    // 2新增或删除属性无法监听
    // 3数组响应化需要额外实现,导致语法有限制,如数组length无法操作数组,通过$set等方法实现
  </script>
</body>
</html>
原文地址:https://www.cnblogs.com/zwhbk/p/12431464.html