实现Vue中的Getter
- 在HTML文件中引入自己创建的vue.js.
- 在vue.js中定义Vue类和构造函数.
- vue.js中定义一个数据劫持的方法
- 使用Object.keys(obj).forEach获取对象所有的键。
下面是html结构
<body>
  <div id="app">
    <h2>姓名:{{name}}</h2>
    <h2>年龄:{{age}}</h2>
  </div>
  <script src="./vue.js"></script>
  <script>
    const vm = new Vue({
      el: '#app',
      data: {
        name: '张三',
        age: 20,
        info: {
          a: 'a1',
          c: 'c1'
        }
      }
    });
    console.log(vm);
  </script>
</body>下面是我们自建的vue.js文件:
class Vue {
  constructor(options) {
    this.$data = options.data;
    // 调用数据劫持的方法
    Observe(this.$data);
  }
}
// 定义一个数据劫持的方法
function Observe(obj) {
  Object.keys(obj).forEach((key) => {
    let value = obj[key];
    Object.defineProperty(obj,key,{
      enumerable: true,
      configurable: true,
      get() {
        console.log(`有人获取${key}的值`);
        return value;
      },
      set(newVal) {
        value = newVal
      }
    })
  })
}上面的Observer函数存在一个问题,就是只将对象的第一层属性添加了getter和setter,却没有对深层次的属性添加,因此下面使用递归解决这个问题。
使用递归为对象上的所有属性添加getter和setter
// 定义一个数据劫持的方法
function Observe(obj) {
  
  // 递归结束条件
  if (!obj || typeof obj !== 'object') {
    return;
  }
  Object.keys(obj).forEach((key) => {
    let value = obj[key];
    Observe(value);
    Object.defineProperty(obj,key,{
      enumerable: true,
      configurable: true,
      get() {
        console.log(`有人获取${key}的值`);
        return value;
      },
      set(newVal) {
        value = newVal
      }
    })
  })
}主要就是看从哪里开始递归,以及递归的终止条件是什么。
上面的Observe函数还存在着一个问题,那就是加入为对象的属性赋值会覆盖掉原本的setter和getter。
为新赋值的对象也添加getter和setter
为了解决上面提到的问题,我们在调用属性的setter方法时,也需要再次将对象投入Observe递归中。
// 定义一个数据劫持的方法
function Observe(obj) {
  
  // 递归结束条件
  if (!obj || typeof obj !== 'object') {
    return;
  }
  Object.keys(obj).forEach((key) => {
    let value = obj[key];
    Observe(value);
    Object.defineProperty(obj,key,{
      enumerable: true,
      configurable: true,
      get() {
        console.log(`有人获取${key}的值`);
        return value;
      },
      set(newVal) {
        value = newVal
        Observe(value)
      }
    })
  })
}总结
要想给vue实例上的data进行数据劫持,需要考虑数据类型,递归,getter和setter时什么时候调用递归等等问题。










