Well, let’s cut to the chase. I do not know whether we have the same learning habits as me, is a step by step from nothing to achieve a principle. It’s like upgrading to fight monsters. It’s fun to upgrade equipment bit by bit. Every time I add the code, it corresponds to git commit, after all, many files, directly in a article is difficult to describe clearly.

It’s hard to write. Sometimes it’s one thing to understand and another thing to write

Post two old photos

At that time, I prepared for about a week and shared it in the group, which can also be regarded as the highlight moment recorded in the previous company. Unfortunately, all my ideas were left on the paper at that time, so I recorded it in the Nuggets this time.

0 directory

  • 1 Preparations
  • 2 VUE object data hijacking
  • Vue array data hijacking
  • 4 Template Compilation
  • 5 Publish and subscribe mode
  • 6 Dependent Collection
  • .
  • Finally, my contact information

1 Preparations

This stage of the code git address: github.com/Ace7523/vue… Because my habit of learning is to add functionality step by step from simple to complex. If you look at the corresponding version of the commit, this part of code corresponds to the first commit.

Webpack will create a new VUE project, I believe this is already known, I don’t need to go into details. I will provide the git address of the code for each stage. One thing that needs to be emphasized is the change here:

Import reference dependencies are first searched in the specified directory, and then searched in node_modules if they cannot be found.

By the way, what is the difference between es6 export and export default? Because there are two ways to write es6 export

A: Export default can only have one file. Import XXX from…

Import {XXX} from… import {XXX} from…

2 VUE object data hijacking

This stage of the code git address: github.com/Ace7523/vue… Corresponding to the first COMMIT

Two questions: 1. Vue is data-driven. 2. How to achieve data-driven?

A: Data-driven is my personal understanding that data comes first, as long as the data changes, the page changes with it, without having to worry about which DOM position the data should be associated with in the page, and then manually change it.

A: Hijacking data, such as a var a = 10, when reading a, knowing that it is reading, when assigning to a, knowing that it is assigning. This is the hijacking of data.

Since I have provided the complete code address, I will look at the key points in the screenshot

1 Create your own VUE instance

2. Use Object.defineProperty to hijack the Object returned by the data method in the figure above. Let’s take a look at the data representation before hijacking:

Write data hijacking method

DefineProperty is used to rewrite the get and set of each attribute of the Object. After doing so, let’s print the data and see:

Name age testObj has a get attribute and a set attribute, so what does that do? Let’s modify the code a little bit more, as follows

To find out, run the following statement (to explain _data, the value of data hangs on _data of the VM instance)

console.log( vm._data.name )
Copy the code

The print result is as follows:

This indicates that the statement printed before attempting to read the value of the name property, i.e., implements data hijacking. The same goes for Settings.

3 Perfect the above hijacking, because the object also contains objects inside this situation is not implemented in the code

The testObj object is an internal object that also has set and get

4. Delegate vm._data to vm and set the value to vm.name

Is through such a method to achieve, you have a good look

5 subtotal

This phase of the code is not difficult, in fact, step by step, each phase of the code is not difficult, the rare is, later on when talking about dependency collection, do not remember this section of logic, so be sure to digest.

Vue array data hijacking

This stage of the code git address: github.com/Ace7523/vue… This corresponds to the second COMMIT.

Why do a special hijacking of an array? Because of the extent to which objects are currently hijacked, there is no way to listen to an element of array push, for example: test the following diagram

Look at the print:

This is definitely not what we want, for example, the page renders the button according to the number of elements in the array, but the array elements are dynamically returned by the interface, although the array has been hijacked, but when we add elements, we do not know that the array is new, that is not good.

Modify the following in the Observer constructor for data hijacking to rewrap the hijacking method for arrays

ArrayMethods observerArray These two methods are written in a separate array.js file. If an array is found during data hijacking, the array’s prototype pointer is changed first, and then the array is hijacked. This is explained in code

In fact, a little more commonly said, is to rewrite the array of push methods, such as the original push method should retain all, but also increase. Array.prototype: rewrites only hijacked Array elements, not changes array. prototype directly. Implement it as follows

In conjunction with the above changes, first of all, when the object is hijacked as an array, the array’s prototype pointing has been changed

data.__proto__= arrayMethods
Copy the code

The arrayMethods is a prototype that inherits the native array, so all the methods will be present. At this point, we just need to modify the methods that need to be changed. The seven methods in the figure change the original array, so they need to be reworked. To illustrate, the figure above can not be modified at all for the 7 methods, but there are places where you can add some operations to the 17 lines in the figure. In fact, this is called slice programming, which is to keep the old features, but add new features.

A few more words, for fear that there will be friends here do not understand. Starting from the hijacking, when it was determined that the data type to be hijacked was array, it first changed the prototype of the hijacked array. For example, when arr. Push was executed again after hijacking, the push method was not obtained from the prototype chain of the native array, but from the array.js we wrote. Because that’s how it’s executed

Arr. Push () is arrayMethods.push() arrayMethods.push = function(... args){ let r = oldArrayProtoMethods[push].apply(this,args); // return r}Copy the code

If apply does not understand, it is suggested to supplement the js foundation. We then refine the method by noting that the second argument to apply is an array. Look at the code

Perhaps some js foundation is not solid small partner to ask again,… What’s args, what’s args in apply. A:… The residual operator is used in function arguments when it is not known how many arguments there are

fun(... The args) {the console. The log (args)} fun (1, 2, 3, 4) / / print the results in [1, 2, 3, 4]Copy the code

Inserted = [4], change the arr to [1,2,3,4] of the original array [1,2,3], and we definitely need to hijack the new element. That’s what makes arrays responsive all the time. Add the following code

Inserted is an array, so it is iterated over, rehijacking each newly added item. All right, let’s add some code to test the new feature points in this section.

The result is as follows

This section adds hijacking of arrays in the data parameter of initializing vue instances. In fact, it is not difficult, but it is difficult to describe this part in the form of an article, but I also posted the code address of this part, you can see the principle of it down.

It should be noted that vUE data hijacking has drawbacks. 1 cannot monitor the index of an array. 2 Arr. length = 0 is not monitored. I just need to make an impression.

4 Template Compilation

The code in this section corresponds to the third commit.

So far, we have done some operations on the data of the new MyVue instance without rendering the data to the page, so this section mainly completes rendering the data to the page. Compilation is not the focus of this article, and there will be a separate article to write compilation.

1 what is compilation, the following diagram can be very intuitive to show

The first step is to add templates

The second step is to modify the initialization logic and, if there is a template, execute the render logic

Step 3, vm._update()

Step 4, compile. That is, the concrete implementation of compiler(Node, VM).

Fifth, replace the text, the concrete implementation of util.compilerText().

It’s important to note that this is the first read of name. Again, the above mentioned data hijacking,, this first read, must be a great foreshadowing

5 Publish and subscribe mode

In this section, I’m going to talk about publish-subscribe, so I’m going to talk about publish-subscribe separately, and then I’m going to change the code. The corresponding code is the fourth COMMIT.

What is the publish subscribe model?

In a more popular way, for example, I have a wechat public account, and if I have 10 friends following me, then ONE day I post an article, and I tell all my friends who subscribe to me to reply “1” and send them a red envelope after replying. So that’s publishing subscriptions, you have subscribers, you notify subscribers when your subscription changes.

Let’s use a new example to illustrate the above code

2. Use of publish subscription model

Without going into the code, let’s figure out how the publish and subscribe model works. Now that I understand the above code, LET me clarify the relationship between them.

  • 1 What is DEP? Dep is a new out instance that can hold watcher.

  • 2 What is watcher? Watcher is an object that has an update method on it.

  • 3 the watcher is the observer. Yes, who is the observed? A: There is no observed in the previous example, because the DEP is an instance of watcher, and an object is observed only if it is bound to the DEP. Because if we have an object {num: 9}, we want to do something when num changes in the object, so we need an intermediate medium to hold all the observers, as follows

    {num: 9, dep: {subs: [watcher1, watcher2… , notify: ()={… }}}

  • 4 How do I respond? In some cases, if we change the value of num on an object and then trigger notify on the deP property of the object, all observers of the object can respond.

3 How is it used in VUE?

A: VUE is data-driven. The data attribute in the instance has a lot of data attached to it. In this example, name and age are observed respectively. When the value of age changes, it causes all watchers on the DEP owned by age to trigger an update.

6 Dependent Collection

I am about to reach the most difficult place to understand, and I find it increasingly difficult to put into words. This section corresponds to the fifth commit of the code.

If you see here, I still hope that the above content has been well absorbed, otherwise the following dependency collection is very easy to dizzy!!

1 create watcher. Js

Back in the Watcher constructor, remember that the second argument is a function. This function, the one that compiles the template, takes the data from data to the function that replaces the value in {{name}}. As soon as this function is executed, it will trigger the get interceptor for vm.name, right? This is important.

PushTarget (this) = pushTarget(this); pushTarget(this) = pushTarget(this); What is this? This is the constructor’s this, which is the new Watcher instance.

Moving on, go back to the original data hijacking and make the following changes

Focus here

if (Dep.target) {
    dep.addSub(Dep.target)
}
Copy the code

What is dep.Target? That’s the new Watcher. The watcher is stored in the DEP, which is bound to the name property. When the value of name changes, that is, when the set interceptor of name is used, the notify of the DEP is executed, and the Watcher update is executed, which holds the rendering template method, so the page is updated.

Here,,, is very complicated, and it should be difficult to read the text description, but I don’t know how to draw a picture to describe this process. The code corresponds to the fifth submission, so let’s just look at the code.

Let me summarize this part of the process

  • 1 Create a VUE instance with data attributes, such as data.name. And at the same time there are templates,
    {{name}}

    There is no doubt about that.

  • Vue will combine data.name with
    {{name}}

    Compile to change to

    Ace7523
  • 3 Then during compilation, data. Name will be read.
  • 4 Data. name Before obtaining the value, the data interception is written and a NEW DEP instance is created, which is used to store the Watcher.
  • There are ways to re-render pages in watcher
  • 6 Whenever data.name is reassigned, the set interceptor will go to dep.notify().
  • 7 Notify will let the method in Watcher re-render the page execute, thus completing the page update.

Finally, my contact information

Limited writing skills, some places feel it is difficult to directly describe clearly, we do not understand the place, you can directly add me to ask me, we discuss, add me when marked is nuggets.