Vue中的数据代理-原生js模拟vue代理原理

46 阅读1分钟

使用数据代理的好处:

1.能通过vm.xxx操作数据,而不是vm._data.xxx操作数据,简化操作

2.为后续的响应式数据做铺垫

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    const _data={
    name:"小米"
  }
  const vm={}
  Object.defineProperty(vm,'name',{
    get(){
      console.log("我是数据代理,我能通过vm对象访问另一个对象的内容");
      return _data.name
    },
    set(value){
      console.log("我是数据代理,我能通过vm对象修改另一个对象的内容");
      _data.name = value
    }
  })
  vm.name="你好"
  console.log(vm.name);
  //这样做的好处:
  //1.能通过vm.xxx操作数据,而不是vm._data.xxx操作数据,简化操作
  //2.为后续的响应式数据做铺垫
  </script>
</body>
</html>

在vue中的实际表现

<div id="app">
  <p>{{ name }}</p>
  <button @click="changeName">改名</button>
</div>

<script>
const vm = new Vue({
  el: '#app',
  data: {
    name: '小明'
  },
  methods: {
    changeName() {
      // 直接操作代理后的属性
      this.name = '小红'; // 实际修改的是 _data.name
    }
  }
});

// 通过控制台验证
console.log(vm.name);      // "小明"(代理访问)
console.log(vm._data.name); // "小明"(原始数据)
</script>

实际上 Vue 的实例 vm 通过 Object.defineProperty定义了一个_data,name,get(return _data.name)/set(_data.name=xxx) 实现了对 data 属性的代理和响应式处理。

另外,不推荐使用vue实例直接修改_data的属性,这样会破坏响应式系统,会修改数据但是不会触发响应式系统。