vue3响应式原理

48 阅读1分钟

Proxy

get()方法

 let obj = {
  name:'张三',
  age:19
 }

 //Proxy代理  new Proxy()创建一个代理对象
 //new Proxy(要代理的对象, {get(){}, set(){}})
 let obj2 = new Proxy(obj, {
  get(target, property){
    //target是这个obj对象, property就是我们要访问的这个属性
    return target[property]
  }
 })

 console.log(obj2.name);
 

set()方法

let obj = {
  name:'张三',
  age:19
 }

 //Proxy代理  new Proxy()创建一个代理对象
 //new Proxy(要代理的对象, {get(){}, set(){}})
 let obj2 = new Proxy(obj, {
  set(target, property, newVal){
    //target是这个obj对象, property就是我们要访问的这个属性,newVal是修改的值
    target[property] = newVal;
  }
 })

 obj2.name = '李四';
 

模拟双向绑定的案例

  1. vue3

     <div>
       <p id="showName"></p>
       <input id="input" />
     </div>
    
     <script>
       let obj = {
         name: "张三",
         age: 19,
       };
    
       function myRe(obj) {
         return new Proxy(obj, {
           get(target, property) {
             return target[property];
           },
           set(target, property, newVal) {
             //对象劫持  数据劫持
             document.getElementById("showName").innerHTML = newVal;
             document.getElementById("input").value = newVal;
             target[property] = newVal;
           },
         });
       }
    
       let obj2 = myRe(obj);
       document.getElementById("showName").innerHTML = obj2.name;
       document.getElementById("input").value = obj2.name;
    
       document.getElementById("input").addEventListener("input", (e) => {
         obj2.name = e.target.value;
       });
     </script>
     
    
  2. vue2

       <div>
         <p id="showName"></p>
         <input id="input" />
       </div>
       <script>
         let obj = {};
         let val = "张三";
    
         //通过Object.defineProperty给对象加一个属性txtVal, 值就是初始值
         Object.defineProperty(obj, "txtVal", {
           get() {
             return val;
           },
           set(newVal) {
             val = newVal;
             document.getElementById("showName").innerHTML = newVal;
             document.getElementById("input").value = newVal;
           },
         });
    
         document.getElementById("showName").innerHTML = obj.txtVal;
         document.getElementById("input").value = obj.txtVal;
    
         document.getElementById("input").addEventListener("input", (e) => {
           obj.txtVal = e.target.value;
         });
    

3.vue2和vue3的区别

3.1 vue3中obj换成数组(数组变化可以监听)

let obj = [1, 2, 3];

  function myRe(obj) {
    return new Proxy(obj, {
      get(target, property) {
        return target[property];
      },
      set(target, property, newVal) {
        document.getElementById("showName").innerHTML = newVal;
        document.getElementById("input").value = newVal;
        //对象劫持  数据劫持
        target[property] = newVal;
      },
    });
  }

  let obj2 = myRe(obj);
  document.getElementById("showName").innerHTML = obj2[0];
  document.getElementById("input").value = obj2[0];

  document.getElementById("input").addEventListener("input", (e) => {
    obj2[0] = e.target.value;
  });
  

3.2 vue2中obj换成数组(数组变化不可以监听,set方法没有执行)

 let obj = {};
  let val = [1,2,3];

  //通过Object.defineProperty给对象加一个属性txtVal, 值就是初始值
  Object.defineProperty(obj, "txtVal", {
    get() {
      return val;
    },
    set(newVal) {
      console.log('执行了set....')
      val = newVal;
      document.getElementById("showName").innerHTML = newVal;
      document.getElementById("input").value = newVal;
    },
  });

  document.getElementById("showName").innerHTML = obj.txtVal;
  document.getElementById("input").value = obj.txtVal;

  document.getElementById("input").addEventListener("input", (e) => {
    obj.txtVal[0] = e.target.value;
  });