近期在看Vue3的源码,看完后也根据一些阅读文档的时候的注释,打算手写实现模拟vue3的核心代码,作为读书笔记,方便后续面试的时候进行复习
你需要掌握的知识点
- Proxy & Reflect
- WeakMap
reactive 的实现
typescript
import { isObject } from '@vue/shared'
import { mutableHandlers, ReactiveFlags } from './basicHandler'
// 收集全局的响应式对象,key为传入的target,value为其代理对象
const reactiveMap = new WeakMap()
export function reactive(target) {
// reactive只能接收对象类型
if (!isObject(target)) return
// 避免传入一个已经代理过的对象
// 未代理之前,target.__v_isReactive 为 undefined,代理过,则为true。
// 详情看 mutableHandlers
if (target[ReactiveFlags.IS_REACTIVE]) {
return target
}
// 避免对同一个对象进行多次代理
const reactiveValue = reactiveMap.get(target)
if (reactiveValue) {
return reactiveValue
}
const proxy = new Proxy(target, mutableHandlers)
reactiveMap.set(target, proxy)
return proxy
}
mutableHandlers 的实现
import { track, trigger } from './effect'
import { isObject } from '@vue/shared'
import { reactive } from './reactive'
export enum ReactiveFlags {
IS_REACTIVE = '__v_isReactive'
}
export const mutableHandlers = {
get(target, key, receiver) {
if (key === ReactiveFlags.IS_REACTIVE) {
return true
}
// 收集依赖
// Fernando: 现在不需要知道他是怎么实现的,你只需要知道他在这里的操作就是收集依赖。后续章节我会补上
track(target, 'get', key)
const result = Reflect.get(target, key, receiver)
if (isObject(result)) {
// 实现深度代理,相较于vue2在初期阶段就递归进行数据劫持,性能更好,取值的时候再进行代理
return reactive(result)
}
return result
},
set(target, key, value, receiver) {
const oldValue = target[key]
const result = Reflect.set(target, key, value, receiver)
if (oldValue !== value) {
// 触发更新依赖相关的effect
// Fernando: 现在你不需要知道他是怎么实现的,你只需要知道他在这里会去触发更新即可
trigger(target, 'set', key, value, oldValue)
}
return result
}
}
以上则为 vue3 对象代理的部分骨架代码,后续我会持续更新,github抢先看
https://github.com/Fernando-lu/fernando-vue