Initialize and mount
After new Vue(). Vue initializes by calling the _init function, the init procedure here, which initializes the lifecycle, events, props, methods, data, computed, watch, and so on. The most important of these is setting setters and getters via Object.defineProperty for “reactive” and “dependency collection,” as I’ll explain later, but just to make an impression.
Calling $mount after initialization will mount the component, if it is compiled at run time, i.e. the render function is not present but the template is present, the “compile” step is required.
compile
Compile can be divided into three stages: parse, optimize and generate.
parse
Parse parses data such as instructions, classes, and styles in the Template template using regexes to form the AST.
optimize
Optimize is the ability to mark static nodes, which is an optimization of the Vue compilation process. The diff algorithm skips the static nodes when the interface is updated, reducing the comparison process. The patch performance is optimized.
generate
Generate is the process of converting an AST into a Render function string, resulting in a render string and a staticRenderFns string.
After going through the parse, Optimize, and generate phases, the component will have the Render function needed to render VNode.
responsive
Now comes the responsive core of vue.js.
Getters and setters have been described before, and are bound to object.defineProperty when init, which causes the getter function to be executed when the set Object is read. The setter function is executed when the value is assigned.
When the Render function is rendered, because the value of the desired object is read, the getter function is fired for “dependency collection”, which stores the observer Watcher object into the subs of the subscriber Dep in the current closure. Form such a relationship as shown below.
When the value of an object is changed, the corresponding setter is fired, and the setter notifys each Watcher in the previously “dependency collection” Dep that its value has changed and the view needs to be rerendered. At this point, the Watcher will call update to update the view, and of course there is a patch process and a strategy of using queues to asynchronously update the view, which we’ll talk about later.
Virtual DOM
As we know, the Render function is converted to a VNode node. Virtual DOM is basically a tree based on JavaScript objects (vNodes), which are described by object attributes. In fact, it is just a layer of abstraction from the real DOM. Eventually, the tree can be mapped to the real world through a series of operations. Because Virtual DOM is based on JavaScript objects and does not depend on the real platform environment, it has the ability to cross platform, such as browser platform, Weex, Node, etc.
Here’s an example:
{tag: 'a', /* indicates that this is a child of the tag */ {tag: 'a', /* indicates that this is a child of the tag */ / text: 'click me' /* contents of the tag */}]}Copy the code
You can get it after rendering
<div>
<a>click me</a>
</div>
Copy the code
This is just a simple example; actual nodes have more attributes to mark the node, such as isStatic (whether it is a static node), isComment (whether it is a comment node), and so on.
Update the view
Setters -> Watcher -> update when modifying an object value, how do you update the view?
When the data changes, we perform the Render function to get a new VNode. The simplest and most crude way to get a new view is to parse the new VNode and render it into the real DOM using innerHTML. However, we only changed a small part of the content, which seemed “wasteful”.
So why can’t we just fix what’s changed? This is the time to introduce our “Patch”. We will pass the new VNode and the old VNode into patch for comparison, and get their “differences” through diff algorithm. Finally, we just need to modify the corresponding DOM of these “differences”.
Next, let’s learn each bar!