vue2响应式原理

381 阅读1分钟
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>vue2响应式原理</title>
</head>
<body>
  <script>
    const data ={
      name: 'wyh',
      age: 22,
      friend: {
        friendName: '小夏'
      },
      colors: ['red', 'blue', 'green']
    }

    const oldArrayProto = Array.prototype;
    const newArrProto = Object.create(oldArrayProto); // 获取数组所有方法
    ['push', 'pop', 'shift', 'unshift', 'splice'].forEach(methodName => {
      newArrProto[methodName] = function () {
        console.log('更新视图')
        oldArrayProto[methodName].call(this, ...arguments); //调用数组原生方法
      }
    })
    

    console.log('oldArrayProto', oldArrayProto)
    console.log('newArrProto', newArrProto)

    // 变为响应式数据
    observer(data);
    function observer (target) {
      if (typeof target !== 'object' || target === null) {
        // 不是object return出去
        return target
      }
      if (Array.isArray(target)) { // 是数组需要 把原型变成自己定义的原型 newArrProto
        target.__proto__ = newArrProto;
      }
      for (let key in target) {
        // 递归变为响应式
        defineReactive(target, key, target[key])
      }
    }

    function defineReactive (target, key, value) {

      observer(value); //再次观察变成响应式

      Object.defineProperty(target, key, {
        get() {
          return value
        },
        set (newValue) {
          observer(newValue); //设置的value页观察变成响应式
          if (newValue !== value) {
            value = newValue
            console.log('更新视图操作')
          }
        }
      })
    }
    // data.name = 'coderwyh'
    // data.friend.friendName = 'coderwyh'
    // delete data.age; //无法更新
    // data.test = 'something'// 无法添加  // 需要用到Vue.delete
    data.colors.push('gray') //执行自己编写的数组方法
    console.log(data)
  </script>
</body>
</html>