【源码系列#01】vue3响应式原理(Proxy)

这篇具有很好参考价值的文章主要介绍了【源码系列#01】vue3响应式原理(Proxy)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

专栏分享:vue2源码专栏,vue3源码专栏,vue router源码专栏,玩具项目专栏,硬核💪推荐🙌
欢迎各位ITer关注点赞收藏🌸🌸🌸

在学习 Vue3 是如何进行对象的响应式代理之前,我想我们应该先去了解下 ES6 新增的API ProxyReflect,可参考【Vue3响应式入门#02】Proxy and Reflect 。之后我们再手写下 reactive 和 effect 的源码

Reactive

定义: 接收一个普通对象然后返回该普通对象的响应式代理。等同于 2.x 的 Vue.observable()

const obj = reactive({ count: 0 })

响应式转换是“深层的”:会影响对象内部所有嵌套的属性。基于 ES6 的 Proxy 实现,返回的代理对象不等于原始对象。建议仅使用代理对象而避免依赖原始对象。

reactive.ts

Vue3中响应数据核心是 reactive , reactive 中的实现是由 proxy 加 effect 组合,先来看一下 reactive 方法的定义

import { isObject } from '@vue/shared'
import { mutableHandlers, ReactiveFlags } from './baseHandler'

// key只能是对象;弱引用,更有效的垃圾回收、释放内存 - https://www.zhangxinxu.com/wordpress/2021/08/js-weakmap-es6/
const reactiveMap = new WeakMap()

/**
 * @desc 将数据转化成响应式的数据
 */
export function reactive(target) {
  // issue1
  if (!isObject(target)) {
    return
  }

  // issue2
  if (target[ReactiveFlags.IS_REACTIVE]) {
    return target
  }

  // issue3
  let existingProxy = reactiveMap.get(target)
  if (existingProxy) {
    return existingProxy
  }

  const proxy = new Proxy(target, mutableHandlers)
  reactiveMap.set(target, proxy)
  return proxy
}
  • @issue1 只能做对象的代理,不是对象,return

  • @issue2 代理对象被再次代理 可以直接返回代理对象

    我们可以利用 Proxy 的 get方法,来判断他有没有代理过

    如果访问这个对象的 __v_isReactive 属性,有值就说明代理过了,当然,我们可以约定 __v_isReactive为任何字段

  • @issue3 同一个对象代理多次,返回同一个代理

    用 WeakMap去缓存对象和代理对象的映射关系

    代理完成时,将此对象和代理对象添加到 WeakMap缓存中;在代理之前,去 WeakMap中读取此对象是否有代理对象的映射,若存在,则返回缓存中的代理对象

WeakMap:key只能是对象;弱引用,更有效的垃圾回收、释放内存,详情请参考JS WeakMap应该什么时候使用 « 张鑫旭-鑫空间-鑫生活

baseHandler.ts

mutableHandlers 是 Proxy 的第二个参数 handler对象提取封装而来

  • track () 依赖收集
  • trigger () 触发依赖

这两个函数为 effect 里的方法,effect 为 reactive 的核心,后面我们会详细介绍。先来看一下mutableHandlers 对象的定义

import { track, trigger } from './effect'

export const enum ReactiveFlags {
  IS_REACTIVE = '__v_isReactive',
}

export const mutableHandlers = {
  // 这里可以监控到用户取值了
  get(target, key, receiver) {
    if (key === ReactiveFlags.IS_REACTIVE) {
      return true
    }

    track(target, 'get', key)
    let res = Reflect.get(target, key, receiver)

    // @issue1 
    // 深度代理实现, 性能好 取值就可以进行代理
    if (isObject(res)) {
      return reactive(res)
    }
    return res
  },
  
  // 这里可以监控到用户设置值了
  set(target, key, value, receiver) {
    let oldValue = target[key] // 缓存老值
    let result = Reflect.set(target, key, value, receiver)
    
    if (oldValue !== value) {
      // 值变化了,触发依赖
      trigger(target, 'set', key)
    }
    return result
  },
}

  • @issue1 嵌套对象深度代理。只有在取值时,才会进行深度代理,性能好

    举个例子,看如下代码。当我们对嵌套对象 product.rate 进行取值时,就会触发 get劫持,然后深度代理嵌套对象 product.rate

const product = reactive({
  price: 5,
  quantity: 2,
  rate: {
    value: 0.9
  }
})

shared.ts

共享模块

// 判断是否是JS对象
export const isObject = function(value){
  return typeof value === 'object' && value !== null
}

参考资料

JS WeakMap应该什么时候使用 « 张鑫旭-鑫空间-鑫生活文章来源地址https://www.toymoban.com/news/detail-746532.html

到了这里,关于【源码系列#01】vue3响应式原理(Proxy)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Vue3响应式原理#02】Proxy and Reflect

    专栏分享:vue2源码专栏,vue3源码专栏,vue router源码专栏,玩具项目专栏,硬核💪推荐🙌 欢迎各位ITer关注点赞收藏🌸🌸🌸 以下是柏成根据Vue3官方课程整理的响应式书面文档 - 第二节,课程链接在此:Proxy and Reflect - Vue 3 Reactivity | Vue Mastery 本篇文章将解决 上一篇文章 结

    2024年02月05日
    浏览(61)
  • 【Vue3响应式原理#01】Reactivity

    专栏分享:vue2源码专栏,vue3源码专栏,vue router源码专栏,玩具项目专栏,硬核💪推荐🙌 欢迎各位ITer关注点赞收藏🌸🌸🌸 以下是柏成根据Vue3官方课程整理的响应式书面文档 - 第一节,课程链接在此:Vue 3 Reactivity - Vue 3 Reactivity | Vue Mastery,本文档可作为课程的辅助材料,

    2024年02月08日
    浏览(38)
  • 【手撕源码】vue3响应式原理解析(文末抽奖)

    🐱 个人主页: 不叫猫先生 🙋‍♂️ 作者简介:2022年度博客之星前端领域TOP 2,前端领域优质作者、阿里云专家博主,专注于前端各领域技术,共同学习共同进步,一起加油呀! 💫优质专栏:vue3从入门到精通、TypeScript从入门到实践 📢 资料领取:前端进阶资料以及文中源

    2024年02月03日
    浏览(61)
  • 【源码系列#03】Vue3计算属性原理(Computed)

    专栏分享:vue2源码专栏,vue3源码专栏,vue router源码专栏,玩具项目专栏,硬核💪推荐🙌 欢迎各位ITer关注点赞收藏🌸🌸🌸 传入一个 getter 函数,返回一个默认不可手动修改的 ref 对象 或者传入一个拥有 get 和 set 函数的对象,创建一个可手动修改的计算状态 @issue1 compute

    2024年02月05日
    浏览(51)
  • 【源码系列#04】Vue3侦听器原理(Watch)

    专栏分享:vue2源码专栏,vue3源码专栏,vue router源码专栏,玩具项目专栏,硬核💪推荐🙌 欢迎各位ITer关注点赞收藏🌸🌸🌸 侦听一个或多个响应式数据源,并在数据源变化时调用所给的回调函数 第一个参数可以是不同形式的“数据源”:它可以是一个 ref (包括计算属性

    2024年02月04日
    浏览(62)
  • 【Vue3响应式入门#01】Reactivity

    专栏分享:vue2源码专栏,vue3源码专栏,vue router源码专栏,玩具项目专栏,硬核💪推荐🙌 欢迎各位ITer关注点赞收藏🌸🌸🌸 以下是柏成根据Vue3官方课程整理的响应式书面文档 - 第一节,课程链接在此:Vue 3 Reactivity - Vue 3 Reactivity | Vue Mastery,本文档可作为课程的辅助材料,

    2024年02月08日
    浏览(46)
  • 前端开发攻略---从源码角度分析Vue3的Propy比Vue2的defineproperty到底好在哪里。一篇文章让你彻底弄懂响应式原理。

    Vue的响应式到底要干什么? 无非就是要知道当你 读取 对象的时候,要知道它读了。要做一些别的事情 无非就是要知道当你 修改 对象的时候,要知道它改了。要做一些别的事情 所以要想一个办法, 把读取和修改的动作变成一个函数 ,读取和修改的时候分别调用对应的函数

    2024年04月17日
    浏览(46)
  • vue3响应式原理

    Vue 3 中的响应式原理是通过使用 ES6 的 Proxy 对象来实现的。在 Vue 3 中,每个组件都有一个响应式代理对象,当组件中的数据发生变化时,代理对象会立即响应并更新视图。 具体来说,当一个组件被创建时,Vue 会为组件的 data 对象创建一个响应式代理对象。这个代理对象可以

    2024年02月15日
    浏览(70)
  • Vue3 数据响应式原理

    核心: 通过Proxy(代理): 拦截对data任意属性的任意(13种)操作, 包括属性值的读写, 属性的添加, 属性的删除等… 通过 Reflect(反射): 动态对被代理对象的相应属性进行特定的操作 Vue3的响应式比Vue2好在哪里? 效率更高了,Vue2中假设监听某个对象,该对象中有一万个属性,他要循

    2024年02月11日
    浏览(50)
  • Vue3响应式原理 私

    响应式的本质:当数据变化后会自动执行某个函数映射到组件,自动触发组件的重新渲染。 响应式的实现方式就是劫持数据,Vue3的reactive就是通过Proxy劫持数据,由于劫持的是整个对象,所以可以检测到任何对象的修改,弥补了2.0的不足。 名词解释: **副作用函数:**函数的

    2024年02月10日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包