日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > vue >内容正文

vue

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

發布時間:2023/11/21 vue 53 coder
生活随笔 收集整理的這篇文章主要介紹了 【源码系列#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應該什么時候使用 ? 張鑫旭-鑫空間-鑫生活

總結

以上是生活随笔為你收集整理的【源码系列#01】vue3响应式原理(Proxy)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。