reactive实现:
export type Dep = Set<ReactiveEffect>
export const createDep = (effects?: ReactiveEffect[]): Dep => {
const dep = new Set<ReactiveEffect>(effects) as Dep
return dep
}
type KeyToDepMap = Map<any, ReactiveEffect>
const targetMap = new WeakMap<any, Dep>()
export function effect<T = any>(fn: () => T) {
const _effect = new ReactiveEffect(fn)
_effect.run()
}
export let activeEffect: ReactiveEffect | undefined
export class ReactiveEffect<T = any> {
constructor(public fn: () => T) {}
run() {
activeEffect = this
return this.fn()
}
}
/**
* 收集依赖
* @param target
* @param key
*/
export function track(target: object, key: unknown) {
// 当前不存在执行函数 直接return
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 = createDep()))
}
trackEffects(dep)
// depsMap.set(key, activeEffect)
// console.log(targetMap)
}
/**
* 利用dep依次跟踪指定key的所有effect
* @param dep
*/
export function trackEffects(dep: Dep) {
dep.add(activeEffect!)
}
/**
* 触发依赖
* @param target
* @param key
* @param value
*/
export function trigger(target: object, key: unknown, value: unknown) {
const depsMap = targetMap.get(target)
if (!depsMap) return
const dep: Dep | undefined = depsMap.get(key)
if (!dep) return
triggerEffects(dep)
}
/**
* 依次触发dep中保存的依赖
* @param dep
*/
export function triggerEffects(dep: Dep) {
const effects = isArray(dep) ? dep : [...dep]
for (const effect of effects) {
triggerEffect(effect)
}
}
export function triggerEffect(effect: ReactiveEffect) {
effect.run()
}
function createGetter() {
return function get(target: object, key: string | symbol, receiver: object) {
const res = Reflect.get(target, key, receiver)
track(target, key)
return res
}
}
function createSetter() {
return function set(
target: object,
key: string | symbol,
value: unknown,
receiver: object
) {
const res = Reflect.set(target, key, value, receiver)
trigger(target, key, value)
return res
}
}
const get = createGetter()
const set = createSetter()
export const mutableHandlers: ProxyHandler<object> = {
get,
set
}
export const reactiveMap = new WeakMap<object, any>()
export function reactive(target: object) {
return createReactiveObject(target, mutableHandlers, reactiveMap)
}
function createReactiveObject(
target: object,
baseHandlers: ProxyHandler<any>,
proxyMap: WeakMap<object, any>
) {
const existingProxy = proxyMap.get(target)
if (existingProxy) {
return existingProxy
}
const proxy = new Proxy(target, baseHandlers)
proxyMap.set(target, proxy)
return proxy
}
ref实现:
ref简单类型数据的响应式是通过RefImpl的 get和set实现的,简单数据类型重新赋值调用了set value,复杂数据类型中属性重新赋值是通过get value返回的proxy实例上的代理对象的属性重新赋值实现的。
export const toReactive = <T extends unknown>(value: T): T =>
isObject(value) ? reactive(value as object) : value
export interface Ref<T = any> {
value: T
}
export function ref(value?: unknown) {
return createRef(value, false)
}
function createRef(rawValue: unknown, shallow: boolean) {
if (isRef(rawValue)) {
return rawValue
}
return new RefImpl(rawValue, shallow)
}
class RefImpl<T> {
private _value: T
private _rawValue: T
public dep?: Dep = undefined
public readonly __v_isRef = true
constructor(value: T, public readonly __v_isShallow: boolean) {
this._rawValue = value
this._value = __v_isShallow ? value : toReactive(value)
}
get value(){
trackRefValue(this)
return this._value
}
set value(newValue){
if(hasChanged(newValue,this._rawValue)){
this._rawValue = newValue
this._value = toReactive(newValue)
triggerRefValue(this)
}
}
}
/**
* 收集依赖
* @param ref
*/
export function trackRefValue(ref){
if(activeEffect){
trackEffects(ref.dep || (ref.dep = createDep()))
}
}
/**
*
* 触发依赖
*/
export function triggerRefValue(ref){
if(activeEffect){
triggerEffects(ref.dep)
}
}
export function isRef(r: any): r is Ref {
return !!(r && r.__v_isRef === true)
}