千家信息网

vue2和vue3数据响应式原理分析及如何实现

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,今天就跟大家聊聊有关vue2和vue3数据响应式原理分析及如何实现,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。数据响应式视图跟数据是自动更新
千家信息网最后更新 2026年11月03日vue2和vue3数据响应式原理分析及如何实现

今天就跟大家聊聊有关vue2和vue3数据响应式原理分析及如何实现,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

数据响应式

  • 视图跟数据是自动更新的,数据更新的时候视图是自动的更新的

  • 追踪数据的变化,在读取数据或者设置数据的时候能够做一些劫持的一些操作

  • vue2 使用defineProperty

  • vue3 改用Proxy

使用defineProperty

如何追踪变化

var obj = {}var age Object.defineProperty(obj, 'age', {    get: function() {        consoel.log('get age ...')        return age    },    set: function(val) {        console.log('set age ...')        age = val    }})obj.age =100 //set age ...console.log(obj.age)//get age ...

对象obj在取age属性的时候会调用数据劫持的get方法
在给age属性赋值的时候会调用set方法

那怎么使用Object.defineProperty实现一个数据响应式呢

function defineReactive(data) {  if (!data || Object.prototype.toString.call(data) !== '[object Object]')    return;  for (let key in data) {    let val = data[key];    Object.defineProperty(data, key, {      enumerable: true, //可枚举      configurable: true, //可配置      get: function() {        track(data, key);        return val;      },      set: function() {        trigger(val, key);      },    });    if (typeof val === "object") {      defineReactive(val);    }  }}function trigger(val, key) {  console.log("sue set", val, key);}function track(val, key) {  console.log("sue set", val, key);}const data = {  name:'better',  firends:['1','2']}defineReactive(data)console.log(data.name)console.log(data.firends[1])console.log(data.firends[0])console.log(Object.prototype.toString.call(data))

这个函数defineReactve用来对Object.defineProperty进行封装,从函数名可以看出,起作用就是定义一个响应式数据,封装后只需要传递data,key和val就行
每当从data中读取key的时候触发track函数,往data的key中设置数据时,set函数中的trigger函数触发

数组的响应式

我们通过Array原型上的方法来改变数组的内容不会触发getter和setter
整理发现Array原型中可以改变数组自身内容的方法有7个,分别push pop shift unshift splice sort reverse
vue2 改写了这这7种方法
实现方式:
以Array.propertype为原型创建一个arrayMethods对象,再使用Object.setPropertypeOf(o, arryMethods)将o的__proto__指向arrayMethods

如何收集依赖

使用

该模板中使用数据 name, 我们要观察数据, 当数据的属性发生变化的时候, 可以通知哪些使用的地方,
这就是我们要先收集依赖,即把用到数据name的地方收集起来,然后等数据变化的时候,把之前收集好的依赖循环触发一遍,总结来说就是getter中收集依赖,在setter中触发依赖

使用proxy

Proxy对象用于创建一个对象的代理, 从而实现基本操作的拦截和定义(如属性查找、赋值、枚举、函数掉用等)

const p = new Proxy(target, handler)
  • target

  • 要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。

  • handler

  • 一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。
    reflect是一个内置对象, 他提供拦截javascript操作的方法, 这些方法和Proxy handlers相同

Reflect.set将值分配给属性的函数。返回一个Boolean 如果更新成功则返回true

Reflect.get获取对象身上某个属性的值,类似target[name]

如何实现劫持

const dinner = {  meal:'111'}const handler = {  get(target, prop) {    console.log('get...', prop)    return Reflect.get(...arguments)  },  set(target, key, value) {    console.log('get...', prop)    console.log('set',key,value)    return Reflect.set(...arguments)  }}const proxy = new Proxy(dinner, handler)console.log(proxy.meal)console.log(proxy.meal)

代码中dinner 对象代理到handler上
跟defineProperty区别
defineProperty的属性需要遍历才能监管所有属性

使用proxy可以将对象所有属性进行代理

用proxy实现一个模拟响应式

function reactive(obj) {  const handler = {    get(target, prop, receiver) {      track(target, prop);      const value =  Reflect.get(...arguments);      if(typeof value === 'Object') {        reactive(value)      }else {        return value      }    },    set(target,key, value, receiver) {      trigger(target,key, value);      return Reflect.set(...arguments);    },  };  return new Proxy(obj,handler)}function track(data, key) {  console.log("sue set", data, key);}function trigger(data, key,value) {  console.log("sue set", key,':',value);}const dinner = {  name:'haochi1'}const proxy  =reactive(dinner)proxy.nameproxy.list = []proxy.list.push(1)

执行后自动打印

思考:为啥只在get中使用递归,set不使用呢?

赋值也需要先get

简单总结:

  1. vue2 (浅响应式)

  • 遍历data,使用defineProperty拦截所有属性

  • 当用户操作视图,会触发set拦截器

  • set先改变当前数据, 再通知wartch, 让watch去通知视图更新

  • 视图重绘, 再次从get中获取对应的数据

  1. vue3 (深度响应式) :

  • 使用proxy 进行代理;拦截data任意属性的任意操作(13种), 包括属性的读写, 属性的添加, 属性的删除等等

  • 使用Reflect进行反射; 动态对被代理的对象的相应属性进行特定的操作

  • 代理对象(proxy)的反射对象(reflect)必须相互配合才能实现响应式

两者的不同

Proxy能劫持整个对象,而Object.defineProperty只能劫持对象的属性; 前者递归返回属性对应的值的代理即可实现响应式,后者需要深度遍历每个属性,后者对数组的操作很不友好.

看完上述内容,你们对vue2和vue3数据响应式原理分析及如何实现有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注行业资讯频道,感谢大家的支持。

属性 数据 对象 函数 代理 方法 时候 内容 数组 视图 更新 变化 原型 就是 原理 分析 地方 深度 递归 反射 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网扶贫科技 互联网最新的科技有限公司 北京互联网科技公司 互联网科技革命 天津摩尔互联网科技 互联网科技汛 成都狮子座互联网科技 上海亿帐通互联网科技 开启互联网科技时代小说 西藏七维空间互联网科技有限公司 互联网公司科技股 黑科技闪耀互联网之光 银川新华互联网科技学校联系电话 用友工业互联网科技发展 互联网公司高科技产品 互联网科技快讯热点 互联网时代科技型公司的机会 互联网科技和医药行业 安徽零酒互联网科技有限公司 广东猫王互联网科技有限公司电话 狮子座互联网科技有限公司 字节跳动和互联网科技 重庆互联网医院沙龙医盟信息科技 岳阳华臻互联网科技有限公司 国大互联网教育科技有限公司工作 乌苏新华互联网科技做什么的 科技类公司包括互联网吗 互联网时代的科技公司 科技互联网专业工作会议发言稿 互联网大会出现的黑科技
0