当前位置: 首页> 科技> 能源 > 湘潭seo_电子商务排名_友情链接实例_如何建立网页

湘潭seo_电子商务排名_友情链接实例_如何建立网页

时间:2025/7/12 20:36:46来源:https://blog.csdn.net/Jet_Lover/article/details/145816848 浏览次数:0次
湘潭seo_电子商务排名_友情链接实例_如何建立网页

Object.defineProperty 与 Proxy 对比

  • 前言
  • 一、Vue2 的响应式原理
  • 二、Vue3 的响应式原理
  • 三、性能优化
  • 总结

前言

响应式系统是 Vue 框架的核心机制之一,通俗易懂的来说 vue2需要手动登记,只有被用到的才会被记录vue3全自动监控

一、Vue2 的响应式原理

  1. 核心实现:Object.defineProperty
    Vue2 的响应式通过 数据劫持 实现,其核心是对对象属性的 getter 和 setter 进行拦截。
// 定义响应式对象
function defineReactive(obj, key, val) {const dep = new Dep(); // 依赖收集容器(每个属性对应一个 dep)Object.defineProperty(obj, key, {enumerable: true,configurable: true,get() { dep.depend();   // 收集依赖:将 Watcher 添加到 dep 中 return val;},set(newVal) {if (newVal === val) return;val = newVal;dep.notify(); // 触发更新:通知所有 Watcher 执行回调}});
}// 递归遍历对象属性
function observe(obj) {if (typeof obj !== 'object' || obj === null) return;Object.keys(obj).forEach(key => {defineReactive(obj, key, obj[key]); // 登记监控 key});
}
  1. 依赖收集与触发机制
  • Dep 类:每个属性对应一个 Dep 实例,用于存储所有依赖该属性的 Watcher。
  • Watcher 类:代表一个视图或计算属性的依赖,当数据变化时触发回调。

依赖收集流程

  • 组件渲染时触发 getter。
  • 将当前 Watcher(如渲染函数)添加到 Dep 的订阅列表中。

触发更新流程

  • 属性被修改时触发 setter。
  • 通过 dep.notify() 通知所有订阅的 Watcher 执行更新。
  1. 局限性
  • 无法检测新增/删除对象属性
    需使用 Vue.set() 或 Vue.delete() 强制触发响应。
// 动态属性添加 API
function set(target, key, val) {if (Array.isArray(target)) {target.length = Math.max(target.length, key)target.splice(key, 1, val)return val}if (key in target) {target[key] = valreturn val}const ob = target.__ob__if (!ob) {target[key] = valreturn val}defineReactive(ob.value, key, val)ob.dep.notify()return val
}
  • 数组需要特殊处理
    Vue2 重写了数组的 push、pop 等方法,需通过原型链劫持实现响应式。
// 数组原型劫持
const arrayProto = Array.prototype
const arrayMethods = Object.create(arrayProto)const methodsToPatch = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'
]methodsToPatch.forEach(method => {const original = arrayProto[method]def(arrayMethods, method, function mutator(...args) {const result = original.apply(this, args)const ob = this.__ob__// 处理新增元素let insertedswitch (method) {case 'push':case 'unshift':inserted = argsbreakcase 'splice':inserted = args.slice(2)break}if (inserted) ob.observeArray(inserted)ob.dep.notify() // 手动触发更新return result})
})
  • 性能开销大
    初始化时递归遍历对象所有属性,对深层嵌套对象不友好。
    如果对象有 1000 个属性,需要逐个递归,耗时较长。

二、Vue3 的响应式原理

1.核心实现:Proxy
简化版代码实现

// 响应式入口
function reactive(target) {const handler = {get(target, key, receiver) {track(target, key); // 依赖收集const res = Reflect.get(target, key, receiver);if (typeof res === 'object' && res !== null) {return reactive(res); // 递归代理嵌套对象(惰性代理)}return res;},set(target, key, value, receiver) {const oldValue = target[key];const result = Reflect.set(target, key, value, receiver);if (oldValue !== value) {trigger(target, key); // 触发更新}return result;},deleteProperty(target, key) {const hadKey = Object.prototype.hasOwnProperty.call(target, key);const result = Reflect.deleteProperty(target, key);if (hadKey) {trigger(target, key); // 触发更新}return result;}};return new Proxy(target, handler);
}// 依赖收集与触发(简化版)
const targetMap = new WeakMap(); // 存储所有响应式对象及其依赖function track(target, key) {if (!activeEffect) return;let depsMap = targetMap.get(target);if (!depsMap) {targetMap.set(target, (depsMap = new Map()));}let dep = depsMap.get(key);if (!dep) {depsMap.set(key, (dep = new Set()));}dep.add(activeEffect); // 存储当前激活的 effect
}function trigger(target, key) {const depsMap = targetMap.get(target);if (!depsMap) return;const effects = depsMap.get(key);effects && effects.forEach(effect => effect());
}
  1. ref 的实现
class RefImpl {constructor(value) {this._value = isObject(value) ? reactive(value) : valuethis.dep = new Set()}get value() {trackRefValue(this) // 依赖收集return this._value}set value(newVal) {if (hasChanged(newVal, this._value)) {this._value = isObject(newVal) ? reactive(newVal) : newValtriggerRefValue(this) // 触发更新}}
}function trackRefValue(ref) {if (activeEffect) {trackEffects(ref.dep)}
}function triggerRefValue(ref) {triggerEffects(ref.dep)
}
  1. 核心改进
  • 动态属性监听
    支持对象属性的动态增删,无需特殊 API。
  • 原生数组响应式
    可直接通过索引修改数组或修改 length。
	const arr = reactive([1, 2, 3]);arr[0] = 10; // 触发更新arr.length = 1; // 触发更新
  • 惰性代理
    只有被用到的属性才会被追踪。,减少初始化开销。
  • 代码更简单
    仅在实际使用的属性上触发更新,不需要处理各种特殊情况。

三、性能优化

  1. 大型对象初始化
// 包含 1000 个属性的对象const bigData = { /* 1000 个属性 */ }// Vue2:立即递归转换所有属性(耗时)const vm = new Vue({ data: { bigData } })// Vue3:按需代理(初始化极快)const state = reactive(bigData)
  1. 动态属性操作
	// Vue2 必须使用特殊APIVue.set(vm.data, 'newProp', value)// Vue3 直接操作state.newProp = value
  1. 数组性能测试
	// 10万条数据数组const bigArray = new Array(1000).fill(null).map((_, i) => ({ id: i }))// Vue2 需要 200ms+ 初始化new Vue({ data: { bigArray } })// Vue3 需要 <10ms 初始化const reactiveArray = reactive(bigArray) 

总结

  • vue2手动登记,只有被用到的才会被记录,vue3全自动监控。
  • vue3性能更优:惰性代理减少初始化开销。
  • vue3代码更简洁。
关键字:湘潭seo_电子商务排名_友情链接实例_如何建立网页

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: