vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > Vue数据拦截器

Vue 3.x与Vue 2.x版本拦截器的对比详解(Vue数据拦截器)

作者:不吃泡面~

在前端开发中,我们经常需要与后端进行数据交互,这篇文章主要介绍了Vue 3.x与Vue 2.x版本拦截器对比的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

数据拦截本身定义

我们对数据进行读写操作时,需要一种机制,能够打断读写操作进行额外的新操作,灵活高效率,这种机制叫做数据拦截。

数据拦截的应用:

Vue和React的组件生命周期钩子函数,本质上就是数据拦截。可以在组件初始化到组件完全渲染出来的时间线里,设置拦截,方便在特定时间进行相关操作。

JS中的数据拦截

主要有两种方式:

  1. Object.defineProperty:用于Vue 1.x、Vue 2.x
  2. Proxy:用于Vue 3.x

Object.defineProperty 拦截API

Object.defineProperty 是Object上的一个静态方法,作用是给一个对象添加新的属性,还能给该属性进行相关配置。

Object.defineProperty(obj, prop, descriptor)

属性描述符可以进行相关详情配置:

默认情况下,使用 Object.defineProperty( ) 添加的属性是不可写、不可枚举和不可配置的。

Object.defineProperty拦截例子:

function Student() {                                             
    let stuName = "张三";
    Object.defineProperty(this, "name", {
      get() {
        return stuName; 
      },
      set(value) {
        if (!isNaN(value)) {
          stuName = "张三";
        } else {
          stuName = value;
        }
      },
    });
  }
  const stu = new Student();
  console.log(stu.name); 
  stu.name = "李四"; 
  console.log(stu.name);
  stu.name = 100; 
  console.log(stu.name);

Proxy 拦截API

是ES6新增的API,通过创建代理对象的方式进行拦截。

const p = new Proxy(target, handler)

Proxy拦截例子:

function proxyStudent() {
const obj = {
  name: "aaa",
};
return new Proxy(obj, {
  get(obj, prop) {
    return obj[prop] + "是个gay!!!";
  },
  set(obj, prop, value) {
    if (!isNaN(value)) {
      obj[prop] = "ggg";
    } else {
      obj[prop] = value;
    }
  },
});
}
const p = new proxyStudent();
console.log(p.name);
p.name = "萨克";
console.log(p.name);
p.name = "111";
console.log(p.name);

两个之间的不同点

1. 拦截的广度:

     function proxyHandle(obj) {
        return new Proxy(obj, {
          get(obj, prop) {
            console.log(`触发get读取操作,读取到了${prop}属性`);
            if (typeof obj[prop] === "object") {
              return deepProxy(obj[prop]);
            }
            return obj[prop];
          },
          set(obj, prop, value) {
            console.log(`触发set写入操作,且开始设置${prop}属性`);
            if (typeof value === "object") {
              return deepProxy(value);
            }
            obj[prop] = value;
          },
          setPrototypeOf(obj, proto) {
            console.log("触发拦截设置原型的操作,开始设置原型!");
            return Object.setPrototypeOf(obj, proto);
          },
          getPrototypeOf(obj) {
            console.log("触发拦截读取原型的操作!");
            return Object.getPrototypeOf(obj);
          },
          deleteProperty(obj, prop) {
            console.log(`触发了删除拦截操作,且删除${prop}属性`);
            delete obj[prop];
          },
        });
      }

2. 性能上的差异:

各有利弊,对于操作类型简单,是某个特定属性时,Object.defineProperty性能最佳。

所以综上来说,大多数情况下,Proxy 是高效的,性能差异是有前提的,看具体的场景。

两个之间的共同点

1. 都可以针对对象成员的读写操作进行拦截:

Object.defineProperty:

const obj = {};
let text = "this is a text";
Object.defineProperty(obj, "content", {
  get() {
    console.log("此时已经触发拦截器get操作");
    return text;
  },

  set(value) {
    console.log("触发拦截器set操作");
    text = value;
  },
});
obj.content = "abcd";
console.log(obj.content);

Proxy:

const obj = {
  content: "this is a text",
  title: "titleA",
};
const pxy = new Proxy(obj, {
  get(obj, prop) {
    console.log("数据读取操作拦截到了");
    return obj[prop];
  },
  set(obj, prop, value) {
    console.log("触发拦截器set操作");
    obj[prop] = value;
  },
});
console.log(pxy.content);
pxy.title = "titleB";
console.log(pxy.title);

2. 都能进行深度遍历拦截:

Objcet.defineProperty:

function deepObjectDefineProperty(obj) {
  for (let key in obj) {
    if (obj.hasOwnProperty(key) && typeof obj[key] === "object") {
      deepObjectDefineProperty(obj[key]);
    }
    let _value = obj[key];
    Object.defineProperty(obj, key, {
      get() {
        console.log("触发get读取操作");
        return _value;
      },
      set(value) {
        console.log("触发set写入操作");
        _value = value;
      },
      configurable: true,
      enumerable: true,
    });
  }
}

const data = {
  obj1: {
    obj2: {
      val: "this is a data",
    },
  },
};
deepObjectDefineProperty(data);
console.log(data.obj1.obj2.val);
data.obj1.obj2.val = "this is a value";

Proxy:

function deepProxy(obj) {
  return new Proxy(obj, {
    get(obj, prop) {
      console.log("get读取操作触发了");
      if (typeof obj[prop] === "object") {
        return deepProxy(obj[prop]);
      }
      return obj[prop];
    },
    set(obj, prop, value) {
      console.log("set写入操作触发了");
      if (typeof value === "object") {
        return deepProxy(value);
      }
      obj[prop] = value;
    },
  });
}
const data = {
  obj1: {
    obj2: {
      val: "this is a data",
    },
  },
};
const proxyData = deepProxy(data);
console.log(proxyData.obj1.obj2.val);
proxyData.obj1.obj2.val = "this is a text";

总结 

到此这篇关于Vue 3.x与Vue 2.x版本拦截器对比的文章就介绍到这了,更多相关Vue数据拦截器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文