Learn VUE source code parsing summary (a)
Writing in the front
Recently, I studied the teacher Huang Yi’s “vue. js source code comprehensive in-depth analysis” course, wrote down some summary, keep notes.
Second, compile,
The reason why the compiler entry logic is so convoluting is that vue. js will be compiled on different platforms, so the baseOptions configuration will be different during compilation. The compilation process will be executed several times, but the configuration of each compilation process on the same platform is the same. In order to prevent these configurations from being passed in through parameters in each compilation process, vue. js uses the function Currization technique to achieve the parameter reservation of baseOptions well. Similarly, vue. js also uses the function currization technique to extract the basic compilation process function, and through createCompilerCreator(baseCompile) the real compilation process and other logic such as compilation configuration processing, cache processing, such a design is very clever.
2. The first step in the compilation process is to parse the template and generate AST, which is an abstract syntax tree and a tree-like representation of the abstract syntax structure of the source code. In many compilation techniques, ES6 code compiled by Babel is encoded as an AST. Parse’s goal is to convert the Template template string into an AST tree, which describes the entire template in the form of JavaScript objects. The whole process of parse uses regular expressions to parse the template in sequence. When parsing the start tag, close tag, and text, the corresponding callback functions are executed to construct the AST tree. There are three types of AST element nodes: type 1 indicates a normal element, type 2 indicates an expression, and type 3 indicates plain text. In fact, HERE I think the source code is not friendly, this is a typical magic number, if converted into a constant expression will be more conducive to read the source code. When the AST tree is constructed, the next step is optimize the tree.
Our template template is exported to the AST tree after parse, so we need to optimize the tree because we know Vue is data-driven and responsive. However, not all data of our template are responsive, and many data will never change after the first rendering, so the DOM generated by this part of data will not change, so we can skip the comparison of them in the process of patch. The process optimize, which deeply traverses the AST tree to determine if each of its subtrees is a static node, will generate a DOM that never needs to change, which is great for runtime updates to the template. With Optimize we mark each AST element node in the entire AST tree as static and staticRoot, which affects how we proceed with code generation.
4. The final step in compiling is to convert the optimized AST tree into executable code. We learned a little bit from the AST -> code step that the compiled code generated is the code executed at runtime.
Five, extension,
1, the event
Vue supports two types of events, native DOM events and custom events. The main difference is that events are added and deleted in different ways. Custom events are distributed to the current instance, but parent components can communicate with each other by defining callback functions in the parent component environment. Note also that only component nodes can add custom events, and adding native DOM events requires the native modifier; The.native modifier is useless for normal elements, and only native DOM events can be added. Native: The logic of add and remove is very simple, which is actually to call native addEventListener and removeEventListener custom: very classic event-centric implementation that stores all events in vm._events when executing the VM.Let CBS = vm._events[event] and execute all the callback functions after emit(event). When performing the vm.Once (event,fn) is the internal execution VM.Off removes the event’s callback, thus ensuring that the callback function is executed only once.
2, v – model
The V-Model works on both normal form elements and components. It’s a syntactic sugar. It’s a true implementation of Vue bidirectional binding, but it’s essentially a syntactic sugar that supports both native form elements and custom components. In the component implementation, we can configure the prop name that the child component receives, and the event name that it dispatches. CompositionStart and compositionEnd events, input start and end events,
3, Slot.
Vue components provide a very useful feature called slot slots, which make component implementation more flexible. In order to make components more flexible and customizable, we often use slots to allow users to customize the content when developing component libraries. Slot is divided into normal slot and scope slot. Normal slot: We know that in normal slot, the data that the parent component applies to the child component slot is bound to the parent component, because the context it renders to the VNode is the instance of the parent component. We looked at the implementation of normal slots and scoped slots. One big difference is the data scope. Normal slots generate vNodes during compilation and rendering of the parent component, so the data scope is the parent component instance, and the child component gets the rendered VNodes directly when rendering. For scopedSlots, the parent component does not generate vnodes directly during compilation and rendering. Instead, it keeps a scopedSlots object in the parent vnode’s data, storing slots with different names and their corresponding rendering functions. The render function is executed to generate vNodes only during the compilation and rendering of the subcomponents, and since it is executed in the subcomponent environment, the corresponding data scope is the subcomponent instance. Simply put, the purpose of both slots is for the content generated by the slot placeholders of the child component to be determined by the parent component, but the scope of the data varies according to their VNodes rendering timing.
4, keep alive
Through analysis we know that the component is an abstract component, its implementation uses the custom render function and slot, and we know how to cache the VNode, and we know how the child element wrapped by the component — that is, how the slot is updated. Mounted is not executed for cached components during patch. Therefore, common component lifecycle functions are not provided, but activated and deactivated hook functions are provided. We also know props, including and exclude, and Max, which controls the number of caches we can use.
5, the Transition
The
component are both built-in components of Vue and abstract components. Automatically sniff out if the target element has CSS transitions or animations applied, and if so, add/remove CSS class names when appropriate.
If the transition component provides JavaScript hook functions, these hook functions will be called at the appropriate time.
3 If the JavaScript hook is not found and CSS transitions/animations are not detected, the DOM operation (insert/delete) is performed immediately in the next frame.
So it’s the CSS or JavaScript hook functions we write that actually perform the animation, whereas Vue just manages the adding/removing of those CSS and the timing of the hook functions.
6, the transition – group
This completes the implementation of the component, which, compared to the component, implements the transition of the list and renders it as a real element. When we modify the data of the list, if we add or delete data, it will trigger the transition animation of the corresponding element itself, which is the same as the implementation effect of the component. In addition, we also realize the transition effect of move, which makes our list transition animation richer.
Six, the vue – the router
1. Vue-router has powerful capabilities. It supports hash, History, and Abstract routing modes, provides two components, and simple route configuration and a series of user-friendly apis
2. Vue provides a global API for vue. use to register these plug-ins
Use takes a plugin parameter and maintains an _installedPlugins array, which stores all registered plugins; The plugin then determines if the install method is defined, and if so, it is called, and the first argument it executes is Vue. Finally, the plugin is stored in installedPlugins. Each plug-in needs to implement a static install method, which is executed when the vue. use plugin is registered. The first parameter of the install method is the Vue object, which has the advantage that the author of the plug-in does not need to import the Vue as it would increase the package size
VueRouter: SRC /index.js VueRouter: SRC /index.js VueRouter: SRC /index.js VueRouter: SRC /index.js
(3) The most important step of vue-router installation is to use vue. mixin to inject beforeCreate and destroyed hook functions into each component. The objects to be mixed will be merged into Vue options through mergeOption. Since each component’s constructor merges vue. options into its own options at the extend stage, each component defines the options defined by the mixin
(4) Vue prototype is definedRoute the get method for the two attributes, which is why we can access this on the component instance.route
(5) Then global and two components are defined by Vue.component method
(6) Matcher, transitionTo navigation guard
(7) Path change is the most important function of routing, we should remember the following: Routing will always maintain the current line, the routing switch when the current line switch to the goal line, switch will perform a series of navigation in the process of guard hook function, can change the url, will also apply colours to a drawing the corresponding component, after the switch to the target line update to replace the current line, it will be used as the basis for the next path switching.
VueRouter (VueRouter) {VueRouter (VueRouter) {VueRouter (VueRouter) {VueRouter (VueRouter) {VueRouter (VueRouter); The history. TransitionTo method is then used to transition routes, which leads to the concept of matcher. Next, we will examine the implementation of matcher.
(9) The analysis of the main process related to Matcher is completed. We understand the concepts of Location, Route, RouteRecord, and so on. And through Matcher’s match method, we can find the matching path Route, which has very important guiding significance for Route switching and component rendering. In the next section, we’ll return to the transitionTo method and see what path switching does.
(10) History. transitionTo is a very important method in vue-router, which is executed when we switch routes
Seven, Vuex
Vuex is a state management mode developed specifically for vue.js applications. It uses centralized storage to manage the state of all components of an application and rules to ensure that the state changes in a predictable way.
The core idea of Vuex is the Store. A “store” is basically a container that contains most of the states in your app. Some students may ask, well, what if I define a global object and then encapsulate some data access interface?
Vuex differs from a purely global object in two ways:
1. Vuex state storage is responsive. When the Vue component reads the state from the Store, if the state in the store changes, the corresponding component is updated efficiently accordingly.
2. You can’t directly change the state in a store. The only way to change the state in a store is to commit mutation explicitly. This allows us to easily track each state change, which allows us to implement tools that help us better understand our application. In addition, by defining and isolating concepts in state management and enforcing compliance with certain rules, our code becomes more structured and maintainable.
3,
4. Initialize vuEX
(1) Vuex initialization process, including installation and Store instantiation process
(2) Just like vue-Router, Vuex also has a static install method. Install’s logic is simple, assigning the passed _Vue to Vue and executing the applyMixin(Vue) method. The beforeCreate hook is used for each of the following functions: store the options.store in this.$store.
(3) After import Vuex, we will instantiate the Store object, return the Store instance and pass it into the options of new Vue, that is, options.store we just mentioned.
(4) The constructor of the Store object receives an object parameter, which includes actions, getters, state, mutations, modules and other Vuex core concepts
(5) Before analyzing the module initialization, let’s first understand the significance of the module for Vuex: Due to the use of a single state tree, all the states of the application will be concentrated into a relatively large object. When the application becomes very complex, the Store object may become quite bloated. To solve these problems, Vuex allows us to split the Store into modules. Each module has its own state, mutation, action, getter, and even nested submodules — split the same way from top to bottom. Therefore, from the perspective of data structure, module design is a tree structure. Store itself can be understood as a root module, and modules below it are sub-modules
(6) At this point, Vuex initialization process is analyzed. In addition to the installation part, we focus on the analysis of Store instantiation process. We want to think of store as a data warehouse. In order to manage the warehouse more conveniently, we split a large store into modules. The modules are a tree structure. Each module defines state, getters, mutations, and actions respectively, and we also completed their initialization by recursively traversing the module. The concept of namespace is also defined for higher encapsulation and reusability of Module. Finally, we defined an internal Vue instance to establish a link between state and getters, and we could monitor state changes in strict mode to see if they were external, and the only way to ensure that state changes were made was to explicitly commit mutation.
(7) Api: store.getters.XXX store.state.XXX
(8) Vuex stores the data store to modify the state in essence, and only allows us to modify the state by submitting mutaion, which is a function. Store provides a commit method for us to submit a mutation. It should be noted that mutation must be a synchronization function, but in the development of actual projects, we often have to send a request first, and then modify the state according to the result of the request. Therefore, the requirements cannot be fulfilled only through mutation. So Vuex gave us a concept of action. An action is similar to mutation, except that it commits mutation rather than operating on state directly, and it can contain arbitrary asynchronous operations. The Store provides a dispatch method to submit an action.
For Vuex, the new Vuex hook will apply the beforeCreate hook function to each component instance. For Vuex, the new Vuex hook will apply the beforeCreate hook function to each component instance. For Vuex, the new Vuex hook will apply the beforeCreate hook function to each component instance. So we can access any properties and methods of the Store in the component.
2. mapState mapGetters mapMutations mapActions
(11) In the Vuex initialization stage, we constructed a module tree and initialized each part of the module. In some cases, we need to inject new modules dynamically. Vuex provides dynamic module registration and a registerModule API on the Store
(12) On the other hand, there is a need for dynamic module registration, and there is a need for dynamic module uninstallation. Vuex provides a dynamic module uninstallation function and an unregisterModule API on store.
(13) Vuex provides plug-in function plugin
In addition to the access capabilities provided by Vuex, it also provides a plug-in capability that allows us to monitor changes in the Store to do some things. Vuex’s Store accepts plugins, which we pass in as an array when we instantiate the Store, and then execute the plugins when we execute the Store constructor. The most common thing we use is Vuex’s built-in Logger plug-in, which tracks state changes and outputs formatted logs
(2) So Vuex plug-in analysis is over. Vuex is designed to support plug-ins, which allows us to track changes inside the Store from the outside. Logger plug-in also provides a good guide during our development stage. Of course, we can also implement Vuex plug-ins to help us meet specific needs.
Learn VUE source code parsing summary (a)
Source code parsing reference links