Vue

Object.definePrototype 有什么不足/缺陷

笔记

Posted by Wason on January 5, 2022

Object.definePrototype 有什么不足/缺陷

前言

vue2 是利用object.defineProtoType 的set 和 get方法 进行数据拦截和监听,使用观察者模式处理,当对象数据发生变化时,对应通知关联/引用的对象数据的。

详述

vue2 的 Object.definePrototype 方式存在的问题是:

  1. Vue 不能检测以下数组的变动:
    • 当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
    • 当你修改数组的长度时,例如:vm.items.length = newLength
  2. Vue 不能检测对象属性的添加或删除

拓展对比

Vue2.0原理:使用Object.defineProperty对象以及对象属性的劫持+发布订阅模式,只要数据发生变化直接通知变化 并驱动视图更新。

语法 
  Object.defineProperty(obj, "name", { 
      get:()=> {}, set:()=> {}
  }) 
  obj: 劫持对象  
  "name": 劫持对象属性  
  { get:()=> {}, set:()=> {}}: 给属性添加set,get方法   

例子 
  let obj = { name: "tom", age: 10 };    
  Object.defineProperty(obj, "name", {       
    get: () => {         
      console.log("访问了name属性");       
    },      
    set: (newVule) => {         
      console.log("设置了name属性");       
    },     
  });     
  obj.name; // 触发get     
  obj.name = "jack"; // 触发set

Vue3.0原理:Vue3.0中的响应式采用了ES6中的 Proxy 方法。Proxy 对象用于定义基本操作的自定义行为(如属性查找、赋值、枚举、函数调用等)

语法
  let p =new Proxy(obj,{get:(target,prop,p)=>{},set:(target, prop, vaule, p)=>{}})
  target: 劫持对象  
  prop: 劫持对象属性  
  vaule: 新的属性值  
  p: 本身  

例子
  // vue3
  let p = new Proxy(obj, {
    get: (target, prop, p) => {
      console.log("获取");
      return prop in target ? target[prop] : "默认值";
    },
    set: (target, prop, vaule, p) => {
      console.log("设置");
      target[prop] = vaule;
    },
});
console.log(p.name); // 访问了name属性
console.log((p.name = "java")); // 设置了name属性

总结

  • vue2通过Object.defineProperty劫持的是对象属性的getter和setter方法
  • vue3通过Proxy劫持的是 整个对象

参考文章

1. vue2和vue3双向绑定的区别是什么
2. Vue3 对比 Vue2.x 差异性、注意点、整体梳理,与React hook比又如何
3. vue2和vue3的双向绑定原理