Write a simple reactive that returns a proxy

function reactive(target: Object) {return new Proxy(target, {get() {track()}, set() {trigger() // notify dependency update, }, has() {}, ownKeys() {} //.... })} // Get is triggered every time a property (target.xxx) is used, and gets collects dependencies. If you use a watchEffect, the watchEffect is a dependency (the watchEffect callback passed in). // If you change the watchEffect to a set, the set will trigger, Trigger is the notification dependency to update, which collects the watchEffect callback, which is executed again. When a change is made in one place, the rest is updated as wellCopy the code

Source part (I have done a part of the deletion, the core part is still the same, the purpose is to better let everyone understand) :

function reactive(target: Object) {if (target && (target as target)[reactiveFlags.is_readOnly]) { Return target} return createReactiveObject(// generate a responsive object, So mutableHandlers are the methods that I wrote up here for get,set, HAS, ownkeys target, false, mutableHandlers, MutableCollectionHandlers / / this is according to the Map, the Set. CreateReactiveObject function createReactiveObject(target: target, // isReadonly: Boolean, // false baseHandlers: ProxyHandler<any>, // get,set a series of methods collectionHandlers: ProxyHandler<any> // for Map, Set, for now) {if (! IsObject (target)) {// reactive only if (__DEV__) {console.warn(' value cannot be made reactive: ${String(target)}`) } return target } // exception: calling readonly() on a reactive object if ( target[ReactiveFlags.RAW] && ! (isReadonly &&target [reactiveFlags.is_reactive]) {return target (reactive (reactiveObject)) If a reactive object is passed in, the proxy will not be re-instantiated, and the current object will be returned. } const proxyMap = isReadonly? readonlyMap : ReactiveMap const existingProxy = proxymap. get(target) // When passing in the same object, the value is directly in the global rroxyMap, If (existingProxy) {return existingProxy} const targetType = getTargetType(target) Target.mon if (targetType === targetType. INVALID) {return target} const proxy = new proxy (// instantiate proxy target, targetType === TargetType.COLLECTION ? collectionHandlers : Set (target, proxy) // Make a WeakMap cache, key is this object, value is proxy, purpose is above, Return proxy // baseHandlers const baseHandlers = {get, Set} const get = (shallow = false) const get = (shallow = false) => { Return function createGetter(target, key, receiver) {return function createGetter(target, key, receiver) {//... Const res = reflect.get (target, key, reactive) const res = reflect.get (target, key, reactive) const res = reflect.get (target, key, reactiveObject, reactive) Receiver) // Get the corresponding value if (! isReadonly) { track(target, TrackOpTypes.GET, key) // ! Collect the dependencies. External call to target.xx will collect the dependencies. For example, if you access target, XXX within watchEffect, this will collect watchEffect dependencies (shallow) {//! Shallow does not change the child element to reactive. For objects provided by third-party libraries, do not change the child element to reactive return res} if (isObject(res)) { Vue will make the child object reactive again. Vue2.0 is a direct recursion of all data. It is better to return isReadonly? readonly(res) : Reactive (res) // Change the object to a reactive object. } return res}} const set = (shallow = false) => {// Set return function createSetter() {const oldValue = (target as any)[key] if (! Shallow) {value = toRaw(value) if (! isArray(target) && isRef(oldValue) && ! IsRef (value)) {// The old value is a ref, but the new value is not a ref, vue does not kill the old ref, Oldvalue. value = value return true}} else {// in shallow mode, objects are set as-is regardless of reactive or not } const result = Reflect.set(target, key, value, Receiver) // Set value if (target === toRaw(receiver)) {if (! hadKey) {trigger trigger(target, TriggerOpTypes.ADD, key, value) } else if (hasChanged(value, OldValue)) {trigger(target, triggeroptypes. SET, key, value, oldValue) // Notify dependencies to update! Track is triggered when the access is needed. Here is the dependency that triggers track collection. (Trigger watchEffect callback function)}} return result}}Copy the code