In this paper, the corresponding source location vue – next/packages/reactivity/SRC/reactive. The ts 181 lines

Personal understanding of the response data type, data update and data acquisition can be used in some way, take the initiative to make the data code to respond, in a nutshell is when the data update and data acquisition can perform other operations, is a return to vue3, data update active triggered by trigger method depend on the function, The dependency function is actively saved through track method when data is obtained.

Front knowledge

The core principles of responsiveness are implemented through Proxy and Reflect. The following is from MDN

Proxy

The Proxy object is used to create a Proxy for an object to intercept and customize basic operations, such as property lookup, assignment, enumeration, function calls, etc.

const p = new Proxy(target, handler)
Copy the code
  • Target: indicates the target object to be proxied
  • Handler: The behavior of a proxy object that performs various operations, usually an object with functions as properties, which have the following two properties
    • Handler.get () : Used to intercept the read property operation of an object, that is, triggered when the property of this object is read
    • Handler.set () : The catcher for the set property value operation, which is triggered when the property value of this object is modified

Reflect

Reflect is an implementation of reflection mechanism introduced in ES6, which allows an application to retrieve some information about itself at runtime. Vue3 uses the following two apis:

  • Reflect.get(target, propertyKey[, receiver]): Reads a property from the object
    • Target: indicates the target object to be set
    • PropertyKey: Key value of the value to be obtained
    • If the receiver:targetObject specified in thegetterAnd for the receivergetterCall thethis
  • Reflect.set(target, propertyKey, value[, receiver]): Sets a property on the object
    • Target: The target object to which the property is set
    • PropertyKey: Specifies the name of the property to be set
    • Value: indicates the value
    • Receiver: If encounteredsetterAnd for the receiversetterCall thethis

Write to see

The core of the reactive principle is to use Proxy to intercept data updates and retrieves and use Reflect to do the same. This is the data proxy. After the data proxy is set, the external data update and fetch operation will go through this layer of proxy, that is, getter and setter will be executed. Therefore, the getter and setter can call the method that collects the dependency and the method that triggers the update respectively. This can be interpreted as having the data be fetched and updated in conjunction with a custom function

So here’s what we need to do:

  1. createProxyProxy target objecttarget
  2. Defining accessorgettersetter
  3. Operating in accessors means collecting dependencies and triggering updates
  4. withReflectComplete the original operation

The code for the ultra-simplified version is shown below

const reactive = target= > {
    return new Proxy(target, {
        get(target, key, receiver) {
            // Collect dependencies
            // track(target, key);
            console.log('collect dependencies... ');

            const res = Reflect.get(target, key, receiver);

            return res;
        },

        set(target, key, value, receiver) {
            // Pay attention to a small detail here: update the value first, then trigger the update method
            const res = Reflect.set(target, key, value, receiver);

            // Trigger the update
            // trigger(target, key);
            console.log('trigger update... ');

            returnres; }}); };const obj = reactive({ a: 1.b: 2 });

obj.a = 100; // trigger update...
obj.b = 200; // trigger update...

console.log(obj.a); // collect dependencies...  
                    / / 100
console.log(obj.b); // collect dependencies...  
                    / / 200
Copy the code

Obj. A: obj. B: obj. B: obj. Collect dependencies… , and also output the modified OBJ. A and OBJ. B, thus achieving the purpose of proxy data, and through track and trigger can actively notify the code using obJ data in the project to update, so as to achieve a very very simple response

conclusion

Personally, Reflect can only match Proxy to better complete the data access operation in the object, rather than the key core of implementation. The responsive core principle of VUe3 is to intercept the access operation by Proxy, and complete the original access operation after collecting track dependence and triggering trigger update method.

Q&A

Q: Why Reflect? A: Reflect.get() and reflect.set () can be replaced by return obj[key] and obj[key]=value. However, there are several reasons why VUe3 chose Reflect as a more troublesome implementation (my opinion only) :

  • The Reflect API makes the underlying code much more robust, but there are strange issues with using Object, such as defining multiple attributes with the same name for an Object that can cause an error
  • The Reflect API is better than the Object API(right). Reflect was introduced in ES6 and is gradually replacing some of Object’s apis through MDN comparison (Compare the Reflect and Object methodsAs you can see, the Reflect API basically replaces the original Object API, and there are additional extension methods, such as the one used hereReflect.get()As well asReflect.set()Most of the differences between the two centers on the type of return. Most Reflect apis return a Boolean to indicate success, while the Object API oddly returns an empty Object,undefined,nullAnd so on. If you use the Reflect API, you can use the return value to do some flow control or determine if an action is being performed as expected, something that most Object apis struggle to do
  • The Reflect API harmonizes standards for object manipulation. The Reflect API implements common object operations as functions. For example, the operations that assign values to properties in an object are provided by ReflectReflect.set()Before that, some people used itobj[key]=valueSome people use itobj.key=valueIt is difficult to form a standard. In addition, Object has many operators, such asdelete,inThe Reflect API does all this in the form of a function

Q: It’s that simple? A: big mistake, the source code in A large number of fault-tolerant processing and special processing, but also the Proxy configuration object and some other object pulled out as parameters needed to receive, and this article to intuitive, wrote in A method directly, this realization and source discrepancy is quite big, but the principle is the same, after the simplified actually is more or less so

Q: Is there anything wrong with you writing so simply? A: There must be A problem, or you have worked so hard to write so much, but I can use this basic, and it looks very simple and clear, the implementation principle is the same, almost