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

 更新时间:2026年08月12日 10:08:26   作者:不吃泡面~  
在前端开发中,我们经常需要与后端进行数据交互,这篇文章主要介绍了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)
  • obj:要定义属性的对象;

  • prop:一个字符串或者Symbol,指定了要定义或者修改的属性键;

  • descriptor:属性描述符。

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

  • get取值函数,默认为undefined;

  • set存值函数,默认为undefined;

  • value设置属性值,默认值为undefined;

  • writable:设置属性值是否可写,默认为false;

  • enumerable设置属性是否可枚举,默认为false;

  • configurable是否可以配置该属性,默认为false:

    • 该属性的类型是否能在数据属性和访问器属性之间更改;

    • 该属性是否能删除;

    • 描述符的其他属性是否能被更改。

默认情况下,使用 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)
  • 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. 拦截的广度:

  • Object.defineProperty:是针对 对象特定属性 进行读写操作。

    • 如果用Object.defineProperty,后期新增的对象属性是拦截不到的。

  • Proxy:是针对 整个对象 进行多种操作。包括*属性的读取、赋值、属性的删除、属性描述符的获取和设置、原型的查看、函数调用等行为*能够进行拦截。

    • 后期新增的对象属性都可以拦截到。

     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数据拦截器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 一篇文章告诉你Vue3指令是如何实现的

    一篇文章告诉你Vue3指令是如何实现的

    在计算机技术中,指令是由指令集架构定义的单个的CPU操作,在更广泛的意义上,“指令”可以是任何可执行程序的元素的表述,例如字节码,下面这篇文章主要给大家介绍了关于Vue3指令是如何实现的相关资料,需要的朋友可以参考下
    2022-01-01
  • vue导出报表至excel表格三种方式

    vue导出报表至excel表格三种方式

    这篇文章主要给大家介绍了关于vue导出报表至excel表格的三种方式,导出报表是实际开发的常见功能,前后端都可以实现表格导出,本文介绍的是用vue实现,需要的朋友可以参考下
    2023-09-09
  • 详解vue结合el-table实现表格小计总计需求(summary-method)

    详解vue结合el-table实现表格小计总计需求(summary-method)

    这篇文章主要介绍了vue结合el-table实现表格小计总计需求(summary-method),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2024-01-01
  • Vue3之路由跳转与参数获取方式

    Vue3之路由跳转与参数获取方式

    这篇文章主要介绍了Vue3之路由跳转与参数获取方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • vue监听浏览器的后退和刷新事件,阻止默认的事件方式

    vue监听浏览器的后退和刷新事件,阻止默认的事件方式

    这篇文章主要介绍了vue监听浏览器的后退和刷新事件,阻止默认的事件方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10
  • npm安装vue脚手架报错警告npm WARN deprecated

    npm安装vue脚手架报错警告npm WARN deprecated

    安装vue脚手架报错可能具体原因比较多,可以根据报错信息进行排查,本文主要介绍了npm安装vue脚手架报错警告npm WARN deprecated,感兴趣的可以了解一下
    2023-11-11
  • vue 动态style 拼接宽度问题

    vue 动态style 拼接宽度问题

    这篇文章主要介绍了vue 动态style 拼接宽度问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • Vue v-html指令详细解析与代码实例(最新推荐)

    Vue v-html指令详细解析与代码实例(最新推荐)

    v-html是Vue.js框架中的一个指令,用于将数据中的HTML代码动态渲染到页面上,它主要用于渲染一些静态的HTML内容或者从后台获取的富文本数据,下面介绍Vue v-html详细解析与代码实例,感兴趣的朋友一起看看吧
    2024-12-12
  • 全面详解vue种数组去重的12种方法示例

    全面详解vue种数组去重的12种方法示例

    这篇文章主要介绍了vue数组去重的12种方法示例全面详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • Vue:Bin Code Editor格式化JSON编辑器详解

    Vue:Bin Code Editor格式化JSON编辑器详解

    文章介绍了BinCodeEditor组件的安装、注册、使用方法以及注意事项,组件可以通过npm或yarn安装,支持全局或局部注册,使用时,可以通过value属性绑定JavaScript值,或使用v-model,组件事件与方法包括编辑区显示问题的解决
    2024-12-12

最新评论