vue3.0中把響應式改成了proxy替代了以前的Object.defineProperty的形式;
vue3.0的包目錄截圖;

其中:
compiler-core:編譯器核心
compiler-dom:針對瀏覽器的編譯模塊
compiler-ssr:針對服務器渲染的編譯模塊
reactivity:響應式系統
runtime-core:運行時核心
runtime-dom:針對瀏覽器運行模塊
shared:共享內容
vue:完整版本
響應式核心,使用的proxy代理和Reflect反射,源碼截圖;

響應式模塊圖1

響應式模塊-proxy代理
Proxy是ES6的新語法,可以直接監聽對象和數組的變化。
Proxy 可以理解成,在目標對象之前架設一層“攔截”,外界對該對象的訪問,都必須先通過這層攔截,因此提供了一種機制,可以對外界的訪問進行過濾和改寫。Proxy 這個詞的原意是代理,用在這里表示由它來“代理”某些操作,可以譯為“代理器”。 ---ECMAScript 6 入門 阮一峰
const observed = new Proxy(target, baseHandle);
new Proxy()表示生成一個Proxy實例,target參數表示所要攔截的目標對象,handler參數是一個配置對象,用來定制攔截行為。
Proxy 有多達13種攔截方法,一共 13 種,具體可以看《ECMAScript 6 入門》阮一峰。
get(target, propKey, receiver):
get方法用于攔截某個屬性的讀取操作,比如proxy.foo和proxy['foo']。
可以接受三個參數,依次為目標對象、屬性名和 proxy 實例本身(嚴格地說,是操作行為所針對的對象)
set(target, propKey, value, receiver):
set方法用來攔截某個屬性的賦值操作,比如proxy.foo = v或proxy['foo'] = v,返回一個布爾值
可以接受四個參數,依次為目標對象、屬性名、屬性值和 Proxy 實例本身
Reflect對象的方法與Proxy對象的方法一一對應,只要是Proxy對象的方法,就能在Reflect對象上找到對應的方法。Reflect也有13種方法和Proxy一一對應;
簡寫reactive -proxy響應式
main.js
import { reactive, effect } from './reactivity'
const obj = reactive({ name: 'zhangsan', age: 18, arr: [1, 2, 3, 4] });
obj.name
obj.name = "lisi"
reactivity/reactive.js
import { moutableHanlder } from './baseHandles'
console.log("====my reactive====");
export function reactive(target) {
return createReactiveObject(target, moutableHanlder)
}
function createReactiveObject(target, baseHandle) {
if (!isObject(target)) {
//判斷是普通值,和null直接返回target
return target;
}
const observed = new Proxy(target, baseHandle);
return observed;
}
reactivity/baseHandles.js
import { reactive } from "../reactivity/reactive";
const get = createGetter();
const set = createSetter();
export const moutableHanlder = {
get,
set
}
function createGetter() {
return function get(target, key, receiver) {
const res = Reflect.get(target, key, receiver)
console.log("=取值==target:" + JSON.stringify(target) + "==key:" + key);
if (isObject(res)) {
//對象里嵌套對象,需要遞歸
return reactive(res)
}
return res;
}
}
function createSetter() {
return function set(target, key, value, receiver) {
const hasKey = hadOwn(target, key);
//判斷上次和這次值是否一致,一致不length操作
const oldValue = target[key];
if (!hasKey) {
console.log("屬性新增操作" + target, key)
} else if (value != oldValue) {
//edit操作
console.log("屬性修改操作" + JSON.stringify(target) + "==key:" + key + "==value:" + value)
}
//其他情況,值沒有發生變化
const res = Reflect.set(target, key, value, receiver);
// console.log("設置值 ===target:" + target + "----key:" + key + "----value:" + value);
// console.log("set-length:" + target.length);
return res;
}
}
控制臺響應截圖:
