preface
In this paper, the high frequency of Vue related interview questions and with detailed answer difficulty is divided into three types of simple medium difficult, you can look at the answer to test their own Vue level ha, if the principle of students interested in welcome to see xiaobian handwritten Vue source series articles If you have a different view of the answer to the students welcome to comment area to add discussion at the end of welcome to click on the link to join the shark brother front group push discussion technology fish for help can be (into the group for free to get Vue2 source mind map ha)
If you think this article is helpful, please remember to like it. Thank you very much!
simple
1 differences between MVC and MVVM
MVC
MVC full name is Model View Controller, Model (Model)- View (View)- Controller (Controller) abbreviation, a software design Model
- Model: The part of the application that processes the logic of the application data. Typically, model objects are responsible for accessing data in the database
- View: The part of the application that handles the display of data. Typically, views are created from model data
- Controller: The part of the application that handles user interaction. Typically, the controller is responsible for reading data from the view, controlling user input, and sending data to the model
The idea behind MVC is that the Controller is responsible for displaying the Model data in the View. In other words, the Controller is responsible for assigning the Model data to the View.
MVVM
The VM class is added to MVVM
- The ViewModel layer: It does two things to achieve bidirectional binding of data. One is to convert the model into the view, which is to convert the data passed in the back end into the page that you see. The way to do this is: data binding. The second is to convert [view] into [model], which is to convert the page you see into data at the back end. DOM event listener.
The biggest difference between MVVM and MVC is: When a property of the Model changes, we don’t have to manually manipulate the Dom element to change the View display. Instead, when we change the property, the View layer display will automatically change (corresponding to the Vue data-driven idea).
Overall, MVVM is much simpler than MVC, not only simplifying business and interface dependencies, but also solving the problem of frequently updating data without having to manipulate DOM elements with selectors. Because in MVVM, the View is not aware of the Model and the View is not observed by the Model and ViewModel, this low coupling pattern improves code reusability
Note: Vue does not fully follow the MVVM philosophy, as the website notes
So the question is why do officials say that Vue does not fully follow MVVM thinking?
- The strict MVVM requirement that the View should not communicate with the Model directly, but Vue provides the $refs property so that the Model can directly manipulate the View, which violates this rule, so Vue is not fully compliant with MVVM.
2 Why is data a function
The data in the component is written as a function, and the data is defined as the return value of the function, so that each time the component is reused, a new copy of data is returned. This is similar to creating a private data space for each component instance and having each component instance maintain its own data. However, simply writing the data in object form causes all component instances to share the same data, resulting in a result that all components will change
3 What are the communication methods of the Vue component
-
The props and $emit parent components pass data to the child component through prop, and the child component passes data to the parent component through the $emit trigger event
-
$parent,$children gets the current component’s parent and the current component’s children
-
$listeners -> A->B->C. Vue 2.4 started with $attrs and $Listeners to address this issue
-
The parent component provides variables via provide, and the child component injects variables via inject. (Not officially recommended for use in real business, but commonly used when writing component libraries)
-
$refs Gets the component instance
-
EnvetBus sibling component data transfer in this case can use the event bus mode
-
Vuex state management
4. What are the lifecycle methods of Vue
BeforeCreate is called after instance initialization and before data Observer and Event /watcher event configuration. During the current phase, data and methods on Data, Methods, Computed, and Watch are not accessible
The created instance is called after it has been created. At this stage, the instance has completed the following configuration: Data Observer, operation of properties and methods, and watch/ Event event callback. There is no $EL, and if you really want to interact with the Dom, you can access it via vm.$nextTick
BeforeMount is called before the mount begins: the relevant render function is called for the first time.
Mounted Occurs after the Dom is mounted. In this stage, real Dom is mounted, data is bi-directional bound, and Dom nodes can be accessed
BeforeUpdate Is called when data is updated and occurs before the virtual DOM is rerendered and patched. You can further change the state in this hook without triggering additional rerendering
Updated occurs after the update is complete. The Dom of the component in the current phase has been updated. It is important to avoid changing the data during this time, as this could result in an infinite loop of updates, and the hook is not called during server-side rendering.
BeforeDestroy Called before the instance is destroyed. At this step, the instance is still fully available. This is where we can put the finishing touches, such as a cleanup timer.
Destroyed Vue is called after the instance is destroyed. When called, everything indicated by the Vue instance is unbound, all event listeners are removed, and all child instances are destroyed. This hook is not called during server-side rendering.
Activated keep-alive only, called when a component is activated
Deactivated keep-alive only, called when a component is destroyed
At what step is the asynchronous request initiated?
Asynchronous requests can be made in the created, beforeMount, and Mounted hook functions because data is already created in these three hook functions and can be assigned to the data returned by the server.
If the asynchronous request does not need to depend on the Dom, it is recommended to call the asynchronous request in the created hook function, because calling the asynchronous request in the created hook function has the following advantages:
- Faster access to server data, reduce page loading time;
- SSR does not support beforeMount and Mounted hook functions, so it is placed in created to facilitate consistency.
5 The difference between v-if and V-show
V-if is converted to a ternary expression during compilation and is not rendered if the condition is not met.
V-show will be compiled as an instruction, and the control style will hide the corresponding node if the condition is not met (display:none)
Usage scenarios
V-if is suitable for scenarios where conditions are rarely changed at runtime and do not need to be switched frequently
V-show is suitable for scenarios that require very frequent switching conditions
Display: None, visibility:hidden, and opacity:0
Talk about vue built-in instructions
7 How to understand Vue unidirectional data flow
Data is always passed from the parent component to the child component. The child component has no right to modify the data passed from the parent component. It can only request the parent component to modify the original data. This will prevent the state of the parent component from changing unexpectedly from the child component, which can cause your application’s data flow to be difficult to understand.
Note: The development environment will be warned if the child component directly binds a prop from the parent component to the V-Model
If you really want to change the parent component’s prop value, you can define a variable in data and initialize it with the prop value. Then use $emit to notify the parent component to change the value
8 Differences between Computed and Watch and application scenarios
Computed is a computed property that depends on other properties to compute values, and computed values are cached and returned only when the computed value changes, and it can set getters and setters.
The watch listens to a change in value and executes a callback, in which some logical operations can be performed.
Computed attributes are commonly used in template rendering, where a value depends on other reactive objects or even computed attributes. The listen attribute is suitable for observing a change in a value to complete a complex piece of business logic
Calculate the attributes of the principle of detailed portal
Listening attribute principle detail portal
9 Why is v-if and V-for not recommended together
Do not use v-for and V-if in the same tag because v-for is parsed before V-if. If you need to use it at the same time, you can consider writing the way to calculate the properties.
medium
Vue2.0 principles of responsive data
The whole idea is data hijacking + observer
Objects are internally hijacked (only existing properties are hijacked) using object.defineProperty via defineReactive methods, and arrays are overridden by array methods. When the page uses the corresponding property, each property has its own DEP property, which holds the watcher that it depends on (dependency collection). When the property changes, the corresponding watcher is notified to update (dispatch updates).
The relevant code is as follows
class Observer {
/ / observations
constructor(value) {
this.walk(value);
}
walk(data) {
// All properties on the object are observed in turn
let keys = Object.keys(data);
for (let i = 0; i < keys.length; i++) {
let key = keys[i];
letvalue = data[key]; defineReactive(data, key, value); }}}// Object.defineProperty Data hijack core compatibility in IE9 and above
function defineReactive(data, key, value) {
observe(value); // Recursive key
// -- if value is still an object, it will continue through odefineReactive until value is not an object
/ / think? If the Vue data is nested too deeply >> performance will suffer
Object.defineProperty(data, key, {
get() {
console.log("Get value");
// We need to do a dependency collection process
return value;
},
set(newValue) {
if (newValue === value) return;
console.log("Setting values");
// We need to do a distribution update processvalue = newValue; }}); }export function observe(value) {
// Hijack properties if the object or array is passed
if (
Object.prototype.toString.call(value) === "[object Object]" ||
Array.isArray(value)
) {
return newObserver(value); }}Copy the code
Responsive data theory detail portal
11 How does Vue detect array changes
Array considering performance reasons not defineProperty an array of each item to intercept, choosing instead to seven kinds of array (push, shift, pop, splice, unshift, sort, reverse) method rewrite (AOP sliced thought)
So changing the index and length of an array in Vue cannot be monitored. You need to change the array through the above 7 mutation methods to trigger the watcher corresponding to the array to update
The relevant code is as follows
// src/obserber/array.js
// Keep the array prototype
const arrayProto = Array.prototype;
// Then we inherit arrayMethods from the array prototype
// Here's slicing oriented programming (AOP) -- dynamically extending functionality without breaking encapsulation
export const arrayMethods = Object.create(arrayProto);
let methodsToPatch = [
"push"."pop"."shift"."unshift"."splice"."reverse"."sort",]; methodsToPatch.forEach((method) = > {
arrayMethods[method] = function (. args) {
// The results of the prototype method are retained
const result = arrayProto[method].apply(this, args);
// This sentence is the key
{a:[1,2,3]} {a:[1,2,3]} {a:[1,2,3]}} {a:[1,2,3]}} {a:[2,3]}} {a:[1,2,3]}}
const ob = this.__ob__;
// A new operation is added to the array
let inserted;
switch (method) {
case "push":
case "unshift":
inserted = args;
break;
case "splice":
inserted = args.slice(2);
default:
break;
}
// If there is a new element inserted, an array is called observeArray of the Observer instance to observe each item in the array
if (inserted) ob.observeArray(inserted);
// We can also detect changes in the array and trigger an update to the view -- the source code will be revealed later
return result;
};
});
Copy the code
An array of observation principles detailed portal
Have you used VUe3.0? How much do you know
-
Vue3.x uses Proxy instead of vue2.x’s object.defineProperty
-
X Using Composition API Setup is an option added to Vue3. It is an entry point to the Composition API within a component.
-
Template syntax change Slot Named slot syntax custom directive V-Model Upgrade
-
Suspense supports fragments (multiple root nodes) and Protal (building content that is rendered in other parts of the DOM) components for specific scenarios. Treeshaking optimized for more built-in functionality.
A summary of new Vue3.0 features and experience with portal
13 Vue3.0 and 2.0 response principle difference
Use Proxy instead of Object. DefineProperty in Vue3. Because Proxy can directly listen for changes in objects and arrays, there are up to 13 intercepting methods.
The relevant code is as follows
import { mutableHandlers } from "./baseHandlers"; // Proxy related logic
import { isObject } from "./util"; // Tool method
export function reactive(target) {
// Create different response objects based on different parameters
return createReactiveObject(target, mutableHandlers);
}
function createReactiveObject(target, baseHandler) {
if(! isObject(target)) {return target;
}
const observed = new Proxy(target, baseHandler);
return observed;
}
const get = createGetter();
const set = createSetter();
function createGetter() {
return function get(target, key, receiver) {
// Radiate the obtained value
const res = Reflect.get(target, key, receiver);
console.log("Attribute fetching", key);
if (isObject(res)) {
// If the value obtained is an object type, return a proxy object for the current object
return reactive(res);
}
return res;
};
}
function createSetter() {
return function set(target, key, value, receiver) {
const oldValue = target[key];
const hadKey = hasOwn(target, key);
const result = Reflect.set(target, key, value, receiver);
if(! hadKey) {console.log("Properties added", key, value);
} else if (hasChanged(value, oldValue)) {
console.log("Property value modified", key, value);
}
return result;
};
}
export const mutableHandlers = {
get, // This method is called when the property is fetched
set, // This method is called when a property is modified
};
Copy the code
14 The sequence of execution of parent-child component lifecycle hook functions for Vue
- Loading the render process
Parent beforeCreate-> parent created-> parent beforeMount-> child beforeCreate-> child created-> child beforeMount-> Child Mounted -> parent
- Child component update process
Parent beforeUpdate-> child beforeUpdate-> child updated-> parent updated
- Parent component update process
Father father beforeUpdate – > updated
- Destruction of the process
Parent beforeDestroy-> child beforeDestroy-> child Destroyed -> parent Destroyed
15 What is the virtual DOM? What are the pros and cons
Because manipulating the DOM in the browser is expensive. Frequent manipulation of the DOM can cause performance problems. This is where the virtual Dom comes in. The Virtual DOM of Vue2 draws lessons from the implementation of snABbDOM, an open source library. The essence of a Virtual DOM is to use a native JS object to describe a DOM node, which is a layer of abstraction of the real DOM.
Advantages:
-
Guaranteed performance lower limit: The virtual DOM of the framework needs to be adapted to any operation that may be generated by the upper-layer API. The implementation of some DOM operations must be universal, so its performance is not optimal. But performance is much better than rough DOM manipulation, so the framework’s virtual DOM at least ensures that you can still provide decent performance without having to manually optimize.
-
No manual manipulation of the DOM: We no longer need to manually operate the DOM, just need to write the code logic of the View-Model, according to the virtual DOM and data two-way binding, help us to update the View in a predictable way, greatly improve our development efficiency;
-
Cross-platform: The VIRTUAL DOM is essentially a JavaScript object, and the DOM is strongly platform dependent. In contrast, the virtual DOM can be more easily cross-platform, such as server rendering, WEEX development, and so on.
Disadvantages:
-
Unable to perform extreme optimization: Although the virtual DOM + reasonable optimization is sufficient to meet the performance requirements of most applications, the virtual DOM cannot perform targeted extreme optimization in some applications with high performance requirements.
-
When rendering a large number of DOM for the first time, the extra layer of virtual DOM computation is slower than innerHTML insertion.
16 v – model principle
V-model is just grammatical sugar
Internally, v-Model uses different properties for different input elements and throws different events:
- Text and Textarea elements use value property and input events;
- Checkbox and radio use checked Property and change events;
- The select field takes value as a prop and change as an event.
Note: For languages that require input methods (such as Chinese, Japanese, Korean, etc.), you will find that the V-Model will not be updated when the input method is used to compose text.
On the normal label
<input v-model="sth" /> // This row is equal to the next row
<input v-bind:value="sth" v-on:input="sth = $event.target.value" />
Copy the code
On the components
<currency-input v-model="price"></currentcy-input>
<! </currency-input> --> <currency :value="price" @input="price = arguments[0]"></currency-input> -->
<! -- Subcomponent definition -->
Vue.component('currency-input', {
template: `
<span>
<input
ref="input"
:value="value"
@input="$emit('input', $event.target.value)"
>
</span>
`,
props: ['value'],
})
Copy the code
17 V-for why do we add key
Without keys, Vue uses an algorithm that minimizes dynamic elements and tries to modify/reuse elements of the same type in place as much as possible. The key is the unique token of the vnode in the Vue. With this key, we can perform diff operations more accurately and quickly
More accurate: since there is no in-place reuse with the key, this can be avoided in the sameNode function a.keey === B.keey comparison. So it will be more accurate.
Faster: Using the uniqueness of the key to generate a map object to obtain the corresponding node, faster than the traversal method
The relevant code is as follows
// Check whether the label and key of two vnodes are the same. If they are the same, the same vnode is reused in place
function isSameVnode(oldVnode, newVnode) {
return oldVnode.tag === newVnode.tag && oldVnode.key === newVnode.key;
}
{'a':0,'b':1} = 'a' in the first position and 'b' in the second position
function makeIndexByKey(children) {
let map = {};
children.forEach((item, index) = > {
map[item.key] = index;
});
return map;
}
// The generated mapping table
let map = makeIndexByKey(oldCh);
Copy the code
Diff algorithm details the portal
18 Vue Event binding principle
Native event bindings are bound to real elements through addEventListener, and component event bindings are implemented through Vue’s custom $ON. If you want to use native events on a component, you need to add the.native modifier, which is equivalent to using a parent component as a normal HTML tag and then adding native events.
$on and $EMIT are based on the published_subscribe mode, maintaining an event center. When on, events are stored in the event center by name, called subscriber, and then emit publishes the corresponding events to execute the corresponding listener in the event center
Handwritten publish subscribe principle Portal
19 Vue-router What is the route hook function and in what order
This section describes the execution process of route hooks. The hook functions are global guard, route guard, and component guard
Complete navigation parsing process:
- Navigation is triggered.
- Call the beforeRouteLeave guard in the deactivated component.
- Calls the global beforeEach guard.
- Call the beforeRouteUpdate guard (2.2+) in the reused component.
- Call beforeEnter in the route configuration.
- Resolve the asynchronous routing component.
- Call beforeRouteEnter in the activated component.
- Call the global beforeResolve guard (2.5+).
- Navigation is confirmed.
- Call the afterEach hook globally.
- Triggers a DOM update.
- Call the callback function passed to next in the beforeRouteEnter guard, and the created component instance is passed as an argument to the callback function.
20 vue-router What is the dynamic route? What is the problem
It is often necessary to map all routes that a pattern matches to the same component. For example, we have a User component that is used to render all users with different ids. So, we can use “dynamic segment” in the vue-router routing path to achieve this effect:
const User = {
template: "<div>User</div>"};const router = new VueRouter({
routes: [
// Dynamic path parameters start with a colon
{ path: "/user/:id".component: User },
],
});
Copy the code
Problem: What should I do if route parameters are invalid because the Vue-Router component is reused?
Solution:
1. Use watch to listen for route parameters and then send the request
watch: { // Use watch to listen for routing changes
"$route": function(){
this.getData(this.$route.params.xxx); }}Copy the code
2. Use :key to prevent “reuse”
<router-view :key="$route.fullPath" />
Copy the code
Talk about my personal understanding of VUEX
Vuex is a global state management system specifically for VUE for data sharing, data caching, etc. (Cannot persist, the internal core principle is to create a global instance new Vue)
It mainly includes the following modules:
- State: A data structure that defines the State of the application, where you can set the default initial State.
- Getters: To allow a component to get data from a Store, the mapGetters helper function simply maps getters in a Store to locally computed properties.
- Mutation: is the only method to change the state in store and must be a synchronous function.
- Action: Used for submitting mutations rather than directly changing state and can include any asynchronous operation.
- Module: Allows a single Store to be split into multiple stores and stored in a single state tree.
22 What can I do if data is lost during THE Vuex page refresh
You need to do THE VUEX data persistence generally use the local storage scheme to save the data you can design your own storage scheme or you can use third-party plug-ins
It is recommended to use the Vuex-Persist plug-in, which is a plug-in created for persistent vuex storage. You do not need to manually access the storage, but directly save the state to a cookie or localStorage
Why does Vuex divide modules and add namespaces
Modules: By using a single state tree, all the state of an application is concentrated into one large object. When the application becomes very complex, the Store object can become quite bloated. To solve this problem, Vuex allows us to split the store into modules. Each module has its own state, mutation, action, getter, and even nested submodules.
Namespaces: By default, actions, mutations, and getters within a module are registered in the global namespace — this enables multiple modules to respond to the same mutation or action. If you want more encapsulation and reuse, you can make your module namespaced: true by adding namespaced: true. When a module is registered, all its getters, actions, and mutations are automatically named according to the registered path of the module.
24 Have you ever used Vue SSR? Tell me something about the SSR
SSR is also called server rendering, which means that Vue renders the tags to HTML on the client side and then returns the HTML directly to the client side.
Advantages:
SSR has better SEO and loads faster on the first screen
Disadvantages: Development conditions are limited, server rendering only supports beforeCreate and Created hooks, special treatment is required when we need some external extension libraries, server rendering applications also need to be in the node.js runtime environment.
There will be a greater load on the server
What design patterns are used in VUE
1. Factory pattern – Pass in parameters to create an instance
The virtual DOM returns the Vnode of the underlying label and the component Vnode depending on the parameter
2. Singleton pattern – The entire program has one and only one instance
The plug-in registration method of vuex and VuE-Router install determines that if an instance exists in the system, it will be returned directly
3. Publish-subscribe pattern (VUE event mechanism)
4. Observer Mode (responsive data principle)
5. Decorator: (@decorator usage)
6. Policy Pattern A policy pattern is when an object has a behavior that can be implemented differently in different scenarios – such as a combination policy of options
. Additional models are welcome
What Vue performance optimizations have you made
This only lists the performance optimization for Vue. The performance optimization of the whole project is a big project and can be written in another article on performance optimization
- Don’t go too deep in the object hierarchy, or performance will suffer
- Do not put data that does not require responsiveness in data (use object.freeze () to freeze data)
- V-if and V-show are used in different scenarios
- Computed and Watch are used in different scenarios
- For v-for traversal, you must add a key, preferably an ID, and avoid using v-if at the same time
- Big data list and table performance optimization – virtual list/virtual table
- To prevent internal leaks, global variables and events are destroyed after the component is destroyed
- Lazy image loading
- The route was loaded lazily. Procedure
- The on-demand introduction of third-party plug-ins
- Use keep-Alive cache components appropriately
- Anti-shaking, throttling application
- Server render SSR or pre-render
difficult
27 Scenarios and principles of vue. mixin
In daily development, we often encounter the same or similar code in different components. The functions of these codes are relatively independent, which can be extracted from the common business logic through Vue’s mixin function. The principle is similar to “object inheritance”. The mergeOptions method is called to merge when the component is initialized, using policy mode to merge the different properties. When components and mixins have options with the same name, these options are “merged” in the appropriate manner.
The relevant code is as follows
export default function initMixin(Vue){
Vue.mixin = function (mixin) {
// Merge objects
this.options=mergeOptions(this.options,mixin) }; }};// src/util/index.js
// Define the lifecycle
export const LIFECYCLE_HOOKS = [
"beforeCreate"."created"."beforeMount"."mounted"."beforeUpdate"."updated"."beforeDestroy"."destroyed",];// Merge policies
const strats = {};
// Mixin core method
export function mergeOptions(parent, child) {
const options = {};
// Go over the father
for (let k in parent) {
mergeFiled(k);
}
// The father has no son
for (let k in child) {
if (!parent.hasOwnProperty(k)) {
mergeFiled(k);
}
}
// True merge field method
function mergeFiled(k) {
if (strats[k]) {
options[k] = strats[k](parent[k], child[k]);
} else {
// Default policyoptions[k] = child[k] ? child[k] : parent[k]; }}return options;
}
Copy the code
Vue. Mixin details the principle of portal
28 nextTick Application scenarios and Principles
The callbacks in nextTick are delayed callbacks that are executed after the next DOM update loop ends. Use this method immediately after modifying the data to get the updated DOM. The main idea is to call asynchronous methods to execute nextTick wrapped methods in a microtask-first way
The relevant code is as follows
let callbacks = [];
let pending = false;
function flushCallbacks() {
pending = false; // Restore flag to false
// Execute the callbacks in sequence
for (let i = 0; i < callbacks.length; i++) { callbacks[i](); }}let timerFunc; // Define an asynchronous method with graceful degradation
if (typeof Promise! = ="undefined") {
// If promise is supported
const p = Promise.resolve();
timerFunc = () = > {
p.then(flushCallbacks);
};
} else if (typeofMutationObserver ! = ="undefined") {
// MutationObserver is an asynchronous method that listens for dom changes
let counter = 1;
const observer = new MutationObserver(flushCallbacks);
const textNode = document.createTextNode(String(counter));
observer.observe(textNode, {
characterData: true}); timerFunc =() = > {
counter = (counter + 1) % 2;
textNode.data = String(counter);
};
} else if (typeofsetImmediate ! = ="undefined") {
// If neither of the preceding supports setImmediate
timerFunc = () = > {
setImmediate(flushCallbacks);
};
} else {
// The last degradation is to use setTimeout
timerFunc = () = > {
setTimeout(flushCallbacks, 0);
};
}
export function nextTick(cb) {
// In addition to rendering watcher, the nextTick is collected into the array along with the user's own manual call
callbacks.push(cb);
if(! pending) {// If nextTick is called multiple times, the flag will be changed to false after the asynchronous queue is cleared
pending = true; timerFunc(); }}Copy the code
NextTick principle detail portal
29 Keep-alive Scenarios and principles
Keep-alive is a component built into Vue that caches components without uninstalling the current component when the component is switched.
-
Two common attributes, include/exclude, allow components to conditionally cache.
-
Two life cycles, activated and deactivated, are used to determine whether the current component is active.
-
Keep-alive also uses the LRU(Least Recently Used) algorithm, which selects the most recently unused components for elimination.
The relevant code is as follows
export default {
name: "keep-alive".abstract: true.// Abstract component
props: {
include: patternTypes, // The component to cache
exclude: patternTypes, // Components to exclude
max: [String.Number].// Maximum number of caches
},
created() {
this.cache = Object.create(null); {a:vNode,b:vNode}
this.keys = []; // Cache component's key set [a,b]
},
destroyed() {
for (const key in this.cache) {
pruneCacheEntry(this.cache, key, this.keys); }},mounted() {
// Dynamic listener include exclude
this.$watch("include".(val) = > {
pruneCache(this.(name) = > matches(val, name));
});
this.$watch("exclude".(val) = > {
pruneCache(this.(name) = >! matches(val, name)); }); },render() {
const slot = this.$slots.default; // Get the slot default value for the package
const vnode: VNode = getFirstComponentChild(slot); // Get the first child component
constcomponentOptions: ? VNodeComponentOptions = vnode && vnode.componentOptions;if (componentOptions) {
// check pattern
constname: ? string = getComponentName(componentOptions);const { include, exclude } = this;
// Disable the cache
if (
// Not included Not included(include && (! name || ! matches(include, name))) ||// Excluded
(exclude && name && matches(exclude, name))
) {
// Return the virtual node
return vnode;
}
const { cache, keys } = this;
constkey: ? string = vnode.key ==null
? // same constructor may get registered as different local components
// so cid alone is not enough (#3269)
componentOptions.Ctor.cid +
(componentOptions.tag ? ` : :${componentOptions.tag}` : "")
: vnode.key;
if (cache[key]) {
// Find the cache by key to get the instance
vnode.componentInstance = cache[key].componentInstance;
// make current key freshest
remove(keys, key); // Delete the key from the array by LRU algorithm
keys.push(key); // Put it at the end of the array
} else {
cache[key] = vnode; // If you don't find it, save it
keys.push(key); // Put it at the end of the array
// Prune simple entry // Delete the 0th item from the array if it exceeds the maximum size
if (this.max && keys.length > parseInt(this.max)) {
pruneCacheEntry(cache, keys[0], keys, this._vnode);
}
}
vnode.data.keepAlive = true; // Indicates that the virtual node has been cached
}
// Return the virtual node
return vnode || (slot && slot[0]); }};Copy the code
What is the LRU algorithm?
The core idea of LRU is that if the data has been accessed recently, it has a higher chance of being accessed in the future, so we insert the component key that hit the cache back into the end of this. Keys. In this way, the data in the header of this. Let’s delete the data that is least likely to be accessed in the future, which is the first cached component in this.keys.
30 Vue.set Principle
Those of you who are familiar with the reactive principle of Vue know that there are two situations where you modify the data and Vue does not trigger an update of the view
1. Add new properties to the instance after it has been created (add properties to reactive objects)
2. Change the array index directly to change the array value
Vue.set, or $set, works like this
For reactive data we added an __ob__ attribute to both the object and the array itself, which represents the Observer instance. When adding a nonexistent property to an object, the new property is first tracked responsively and then the watcher collected by the dep of the object __ob__ is triggered to update it. When changing the array index, we call the splice method of the array itself to update the array
The relevant code is as follows
export function set(target: Array | Object, key: any, val: any) :any {
// If it's an array, call the splice method we overwrote (so we can update the view)
if (Array.isArray(target) && isValidArrayIndex(key)) {
target.length = Math.max(target.length, key);
target.splice(key, 1, val);
return val;
}
// If it is a property of the object itself, add it directly
if (key intarget && ! (keyin Object.prototype)) {
target[key] = val;
return val;
}
const ob = (target: any).__ob__;
// There is no need to define a responsive property if it is not responsive
if(! ob) { target[key] = val;return val;
}
// Define the attribute as responsive
defineReactive(ob.value, key, val);
// Notify view updates
ob.dep.notify();
return val;
}
Copy the code
Responsive data theory detail portal
31 Vue.extend Functions and principles
Extend uses the base Vue constructor to create a “subclass”. A parameter is an object that contains component options.
The constructor is the core API of the Vue component. The idea is that it returns a subclass of Vue using prototype-inherited methods and merges the options of the passed component with the options of the parent class using mergeOptions
The relevant code is as follows
export default function initExtend(Vue) {
let cid = 0; // Unique identification of the component
// Create a subclass that inherits from the Vue parent class to facilitate property extension
Vue.extend = function (extendOptions) {
// Create the subclass constructor and call the initialization method
const Sub = function VueComponent(options) {
this._init(options); // Call the Vue initialization method
};
Sub.cid = cid++;
Sub.prototype = Object.create(this.prototype); // The subclass prototype points to the superclass
Sub.prototype.constructor = Sub; //constructor refers to itself
Sub.options = mergeOptions(this.options, extendOptions); // Merge your options with those of your parent class
return Sub;
};
}
Copy the code
Vue component principle detail portal
Have you ever written a custom instruction
Directives are essentially decorators that are vUE extensions to HTML elements that add custom functionality to HTML elements. When vue compiles the DOM, it finds the instruction object and executes the method associated with the instruction.
A custom instruction has five life cycles (also called the hook function) : bind, inserted, Update, componentUpdated, and unbind
1. Bind: called only once, the first time a directive is bound to an element. This is where you can do one-time initialization. 2. Inserted: Called when the bound element is inserted into the parent node (only ensures that the parent exists, but not necessarily that it has been inserted into the document). 3. Update: called when the template to which the element is bound is updated, regardless of whether the binding value has changed. Unnecessary template updates can be ignored by comparing binding values before and after updates. 4. ComponentUpdated: Called when the template to which the bound element belongs completes an update cycle. 5. Unbind: called only once, when the instruction is unbound from the element.Copy the code
The principle of
1. When the AST syntax tree is generated, the directives are added to the current element
2. Generate the directive code using the genDirectives
3. Extract the hook of the instruction to CBS before patch, and call the corresponding hook during patch
4. When executing the hook function corresponding to the instruction, the method defined by the corresponding instruction is called
33 What are the Vue modifiers
Event modifier
- .stop prevents the event from propagating further
- . Prevent Prevents the label default behavior
- .capture uses the event capture pattern, where events triggered by the element itself are processed before being passed to the internal element for processing
- Self fires the handler only if the event. Target is the current element itself
- The.once event will be triggered only once
- .passive tells the browser that you do not want to prevent the default behavior of the event
Modifier for v-model
-
Lazy, with this modifier, is converted to resynchronization at the change event
-
.number Automatically converts the user input value to a numeric type
-
Trim Automatically filters the first and last Spaces entered by the user
Modifiers for keyboard events
- .enter
- .tab
- .delete (capture “Delete” and “backspace” keys)
- .esc
- .space
- .up
- .down
- .left
- .right
System modifier key
- .ctrl
- .alt
- .shift
- .meta
Mouse button modifier
- .left
- .right
- .middle
34 Vue template compilation principles
The Vue compilation process is to convert the template to the render function in three steps
The first step is to convert the template string to Element ASTs. The second step is to do static node markup on the AST, which is mainly used for rendering optimization of the virtual DOM (optimizer). The third step is to use element ASTs to generate the render function code string (code generator).Copy the code
The relevant code is as follows
export function compileToFunctions(template) {
// We need to turn the HTML string into the render function
// 1. Convert HTML code into an AST syntax tree. The AST is used to describe the code itself, forming a tree structure that describes not only HTML but also CSS and JS syntax
// Many libraries use ast, such as Webpack, Babel, esLint, etc
let ast = parse(template);
// 2. Optimize static nodes
// This interested can see the source code does not affect the core function is not implemented
// if (options.optimize ! == false) {
// optimize(ast, options);
/ /}
// 3. Regenerate the code from the AST
// Our final generated code needs to be the same as the render function
/ / similar _c (' div '{id: "app"}, _c (' div', undefined, _v (" hello "+ _s (name)), _c (' span, undefined, _v (" world"))))
// _c for create element, _v for create text, _s for text json. stringify-- parses the object into text
let code = generate(ast);
// Use the call to render to change the value of the variable in this convenience code
let renderFn = new Function(`with(this){return ${code}} `);
return renderFn;
}
Copy the code
Template compiling principle detail portal
How is the lifecycle hook implemented
The core implementation of Vue’s lifecycle hook implementation is to subscribe to all the lifecycle hooks passed in by the user (stored as an array) and then execute the corresponding hook method (publish) at once during the creation of the component instance.
The relevant code is as follows
export function callHook(vm, hook) {
// Execute the lifecycle methods in turn
const handlers = vm.$options[hook];
if (handlers) {
for (let i = 0; i < handlers.length; i++) {
handlers[i].call(vm); // This in the lifecycle refers to the current instance}}}// When called
Vue.prototype._init = function (options) {
const vm = this;
vm.$options = mergeOptions(vm.constructor.options, options);
callHook(vm, "beforeCreate"); // Before initializing the data
// Initialize the state
initState(vm);
callHook(vm, "created"); // After initializing the data
if(vm.$options.el) { vm.$mount(vm.$options.el); }};Copy the code
Life cycle implementation detail portal
36 Application scenarios and Principles of functional Components
The difference between functional components and ordinary components
1. Functional components need to specify functional:true 2 when declaring the component. There is no need to instantiate, so there is no this. This is replaced by the second argument to the render function, context. There is no lifecycle hook function, no calculated properties can be used, watch 4. You can't expose events from the $emit, and only call events from the context.listeners. Click method 5. Because functional components are not instantiated, an external reference to a component through a REF is actually a reference to HTMLElement 6. A functional component can use props as props, so all properties that are not declared in props are automatically resolved to prop. All undeclared properties of a functional component are resolved to $attrs and automatically mounted to the component root (which can be disabled by using the inheritAttrs attribute).Copy the code
Advantages 1. Because functional components do not need to be instantiated, are stateless, and have no life cycle, rendering performance is better than normal component 2. The functional component structure is simpler and the code structure is clearer
Usage scenario:
A simple presentation component used as a container component such as router-View is a functional component
“High-level component” – used to take a component as a parameter and return a wrapped component
The relevant code is as follows
if (isTrue(Ctor.options.functional)) {
// A functional component is a functional component
return createFunctionalComponent(Ctor, propsData, data, context, children);
}
const listeners = data.on;
data.on = data.nativeOn;
installComponentHooks(data); // Install the component-specific hook (functional components do not call this method and thus perform better than normal components)
Copy the code
37 Can you explain the principle of the routing mode commonly used in vue-Router
Hash pattern
-
The value of location.hash is actually what follows the # in the URL. The feature is that while the hash appears in the URL, it is not included in the HTTP request and has no effect at all on the back end, so changing the hash will not reload the page.
-
You can add listening events for hash changes
window.addEventListener("hashchange", funcRef, false);
Copy the code
Every time you change the hash (window.location.hash), a record is added to the browser’s access history. Using the above hash features, you can implement the “update view without re-requesting page” function of the front-end route
Features: Good compatibility but not beautiful
The history mode
Take advantage of the new pushState() and replaceState() methods in the HTML5 History Interface.
These two methods apply to the browser’s history station and provide the ability to modify the history on top of the existing back, Forward, and go. These two methods have one thing in common: when they are called to modify the browser history stack, the browser does not refresh the page even though the current URL has changed, which provides the basis for a single-page application front end route “update the view but do not re-request the page.”
Features: Although beautiful, refresh will appear 404 needs to be configured on the back end
38 Diff algorithm
It is recommended to see diff algorithm in detail for portal
Series of links (will be updated later)
- Handwriting Vue2.0 source code (a) – response data principle
- Handwriting Vue2.0 source code (2) – template compilation principle
- Handwriting Vue2.0 source code (three) – initial rendering principle
- Handwriting Vue2.0 source code (four) – rendering update principle
- Handwriting Vue2.0 source code (five) – asynchronous update principle
- Handwriting Vue2.0 source code (six) -diff algorithm principle
- Handwriting Vue2.0 source code (seven) -Mixin Mixin principle
- Handwriting Vue2.0 source code (eight) – component principle
- Handwriting Vue2.0 source code (nine) – listening attribute principle
- Handwriting Vue2.0 source code (ten) – the principle of computing attributes
- Handwriting Vue2.0 source code (eleven) – global API principle
- The most complete Vue interview questions + detailed answers
- Handwritten vue-Router source code
- Write vuex source code
- Handwriting vue3.0 source code
Shark brother front touch fish technology group
Welcome technical exchanges within the fish can be pushed for help – link